From 60a3248c6ba71f2f7bb6d69b7b51bb0eb8629f4a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 23 Dec 2024 20:30:32 +0100 Subject: [PATCH 001/109] Adds "Relay n (API failsafe only)" to button's actions Solves #23 --- ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 8 ++ ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 73 +++++++++---------- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index 3029db4..b7be303 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -19,6 +19,10 @@ substitutions: BUTTON_2_ACTION_TEXT: "Relay 2 (toggle)" BUTTON_3_ACTION_TEXT: "Relay 3 (toggle)" BUTTON_4_ACTION_TEXT: "Relay 4 (toggle)" + BUTTON_1_ACTION_FAILSAFE_TEXT: "Relay 1 (API failsafe only)" + BUTTON_2_ACTION_FAILSAFE_TEXT: "Relay 2 (API failsafe only)" + BUTTON_3_ACTION_FAILSAFE_TEXT: "Relay 3 (API failsafe only)" + BUTTON_4_ACTION_FAILSAFE_TEXT: "Relay 4 (API failsafe only)" BUTTON_CLICK_MIN_LENGTH: '50' # The minimum duration the click should last, in msec BUTTON_CLICK_MAX_LENGTH: '350' # The maximum duration the click should last, in msec @@ -289,6 +293,7 @@ select: options: - "${BUTTON_ACTION_NONE_TEXT}" - "${BUTTON_1_ACTION_TEXT}" + - "${BUTTON_1_ACTION_FAILSAFE_TEXT}" initial_option: "${BUTTON_1_ACTION_TEXT}" optimistic: true restore_value: true @@ -303,6 +308,7 @@ select: options: - "${BUTTON_ACTION_NONE_TEXT}" - "${BUTTON_2_ACTION_TEXT}" + - "${BUTTON_2_ACTION_FAILSAFE_TEXT}" initial_option: "${BUTTON_2_ACTION_TEXT}" <<: *button_select_action_base @@ -312,6 +318,7 @@ select: options: - "${BUTTON_ACTION_NONE_TEXT}" - "${BUTTON_3_ACTION_TEXT}" + - "${BUTTON_3_ACTION_FAILSAFE_TEXT}" initial_option: "${BUTTON_3_ACTION_TEXT}" <<: *button_select_action_base @@ -321,6 +328,7 @@ select: options: - "${BUTTON_ACTION_NONE_TEXT}" - "${BUTTON_4_ACTION_TEXT}" + - "${BUTTON_4_ACTION_FAILSAFE_TEXT}" initial_option: "${BUTTON_4_ACTION_TEXT}" <<: *button_select_action_base ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index d9a163e..5735035 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -191,57 +191,56 @@ script: } // Toggle relay if corresponding button action is enabled - ESP_LOGVV("core_hw_relays", "Toggle relays: (${BUTTON_ACTION_NONE_TEXT})"); - ESP_LOGVV("core_hw_relays", " Relay 1: %s (%s)", - YESNO(sl_button_1_action->state != "${BUTTON_ACTION_NONE_TEXT}"), - sl_button_1_action->state.c_str()); - ESP_LOGVV("core_hw_relays", " Relay 2: %s (%s)", - YESNO(sl_button_2_action->state != "${BUTTON_ACTION_NONE_TEXT}"), - sl_button_2_action->state.c_str()); - ESP_LOGVV("core_hw_relays", " Relay 3: %s (%s)", - YESNO(sl_button_3_action->state != "${BUTTON_ACTION_NONE_TEXT}"), - sl_button_3_action->state.c_str()); - ESP_LOGVV("core_hw_relays", " Relay 4: %s (%s)", - YESNO(sl_button_4_action->state != "${BUTTON_ACTION_NONE_TEXT}"), - sl_button_4_action->state.c_str()); + const bool api_disconnected = not global_api_server->is_connected(); + std::string select_state; + bool toggle_relay = false; + if (api_disconnected) { + ESP_LOGW("core_hw_relays", "Toggle relays:"); + ESP_LOGW("core_hw_relays", " API state: DISCONNECTED"); + ESP_LOGW("core_hw_relays", " Button: %" PRIu8, button); + } else { + ESP_LOGVV("core_hw_relays", "Toggle relays:"); + ESP_LOGVV("core_hw_relays", " API state: Connected"); + ESP_LOGVV("core_hw_relays", " Button: %" PRIu8, button); + } switch (button) { case ${BUTTON_1_ID}: - if (sl_button_1_action->state != "${BUTTON_ACTION_NONE_TEXT}") { - ESP_LOGV("core_hw_relays", "Toggle relay 1: (%s)", sl_button_1_action->state.c_str()); + select_state = sl_button_1_action->state; + toggle_relay = (select_state == "${BUTTON_1_ACTION_TEXT}" or + (api_disconnected and select_state == "${BUTTON_1_ACTION_FAILSAFE_TEXT}")); + if (toggle_relay) sw_relay_1->toggle(); - } else { - ESP_LOGV("core_hw_relays", "Ignoring toggle for relay 1: action is '%s'", - sl_button_1_action->state.c_str()); - } break; case ${BUTTON_2_ID}: - if (sl_button_2_action->state != "${BUTTON_ACTION_NONE_TEXT}") { - ESP_LOGV("core_hw_relays", "Toggle relay 2: (%s)", sl_button_2_action->state.c_str()); + select_state = sl_button_2_action->state; + toggle_relay = (select_state == "${BUTTON_2_ACTION_TEXT}" or + (api_disconnected and select_state == "${BUTTON_2_ACTION_FAILSAFE_TEXT}")); + if (toggle_relay) sw_relay_2->toggle(); - } else { - ESP_LOGV("core_hw_relays", "Ignoring toggle for relay 2: action is '%s'", - sl_button_2_action->state.c_str()); - } break; case ${BUTTON_3_ID}: - if (sl_button_3_action->state != "${BUTTON_ACTION_NONE_TEXT}") { - ESP_LOGV("core_hw_relays", "Toggle relay 3: (%s)", sl_button_3_action->state.c_str()); + select_state = sl_button_3_action->state; + toggle_relay = (select_state == "${BUTTON_3_ACTION_TEXT}" or + (api_disconnected and select_state == "${BUTTON_3_ACTION_FAILSAFE_TEXT}")); + if (toggle_relay) sw_relay_3->toggle(); - } else { - ESP_LOGV("core_hw_relays", "Ignoring toggle for relay 3: action is '%s'", - sl_button_3_action->state.c_str()); - } break; case ${BUTTON_4_ID}: - if (sl_button_4_action->state != "${BUTTON_ACTION_NONE_TEXT}") { - ESP_LOGV("core_hw_relays", "Toggle relay 4: (%s)", sl_button_4_action->state.c_str()); + select_state = sl_button_4_action->state; + toggle_relay = (select_state == "${BUTTON_4_ACTION_TEXT}" or + (api_disconnected and select_state == "${BUTTON_4_ACTION_FAILSAFE_TEXT}")); + if (toggle_relay) sw_relay_4->toggle(); - } else { - ESP_LOGV("core_hw_relays", "Ignoring toggle for relay 4: action is '%s'", - sl_button_4_action->state.c_str()); - } break; } + if (toggle_relay) { + ESP_LOGI("core_hw_relays", "Toggle relay %" PRIu8 ": (%s)", button, select_state.c_str()); + } else if (not select_state.empty()) { + ESP_LOGV("core_hw_relays", "Ignoring toggle for relay %" PRIu8 ": action is '%s'", + button, select_state.c_str()); + } else { + ESP_LOGE("core_hw_relays", "No button action selected for button %" PRIu8, button); + } - id: show_relay_status mode: restart From d77d7614974d5d4750e0564f247c0aee0b59a49a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:00:26 +0100 Subject: [PATCH 002/109] Add speaker to BLE Proxy add-on --- ...Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 62 ++++++++++++++++++- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 2 + ...Ultimate-Easy-ESPHome_core_hw_speaker.yaml | 2 +- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 331bda3..20cc2f6 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -11,6 +11,25 @@ ##### - For normal system use, modifications to this file are NOT required. ##### #################################################################################################### --- +substitutions: + tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use to "none" for no sound + +api: + actions: + - action: rtttl_play + variables: + # The RTTTL string for the melody to be played. + # It should follow the RTTTL format, including the melody's name, + # default settings, and a sequence of notes. + tone: string + then: + - lambda: |- + rtttl_speaker->stop(); + if (rtttl_speaker_gain->state > 0) { + ESP_LOGI("api", "Play tone: '%s'", tone.c_str()); + rtttl_speaker->play(tone.c_str()); + } + bluetooth_proxy: esp32: @@ -33,17 +52,54 @@ esphome: build_flags: - -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY -i2s_audio: !remove - light: - id: !extend light_full platform: esp32_rmt_led_strip rgb_order: GRB - rmt_channel: 0 + rmt_channel: 1 chipset: ws2812 type: !remove variant: !remove max_refresh_rate: 33ms + use_psram: true media_player: !remove + +number: + - id: rtttl_speaker_gain + name: Sound - Volume + platform: template + max_value: 100 + min_value: 0 + step: 1 + initial_value: 100 + unit_of_measurement: "%" + internal: false + disabled_by_default: true + entity_category: config + device_class: sound_pressure + restore_value: true + optimistic: true + set_action: + then: + - lambda: |- + rtttl_speaker->set_gain((100-(x/10.0f))/100.0f); + std::string tone_volume_change = "${tone_volume_change}"; + // Play sound if tone_volume_change is not "none" + if (x > 0 and !tone_volume_change.empty() and tone_volume_change != "none") + rtttl_speaker->play(tone_volume_change); + rtttl_speaker->dump_config(); + +rtttl: + - id: rtttl_speaker + speaker: mp_speaker + +speaker: + - id: mp_speaker + platform: i2s_audio + dac_type: external + i2s_dout_pin: GPIO15 + i2s_audio_id: if_i2s_audio + i2s_comm_fmt: stand_msb + channel: mono ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 75bfc76..ac461ef 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -85,6 +85,8 @@ ota: platform: esphome psram: + mode: octal + speed: 40MHz script: - id: api_send_ha_event_boot diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml index 11178ec..7833b18 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml @@ -19,11 +19,11 @@ i2s_audio: media_player: - id: mp_speaker name: Speaker + internal: false platform: i2s_audio i2s_dout_pin: GPIO15 i2s_audio_id: if_i2s_audio i2s_comm_fmt: lsb dac_type: external mode: mono - internal: false ... From a716e8e9cf2c3f98ae370dca7c78cc6ef7e8b71b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 00:22:52 +0100 Subject: [PATCH 003/109] Change media player fmt to `msb` --- ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 4 +++- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 20cc2f6..a18515c 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -12,7 +12,9 @@ #################################################################################################### --- substitutions: - tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use to "none" for no sound + # RTTTL format: name:d=duration,o=octave,b=tempo:notes + # d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100) + tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound api: actions: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml index 7833b18..2addc80 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml @@ -23,7 +23,7 @@ media_player: platform: i2s_audio i2s_dout_pin: GPIO15 i2s_audio_id: if_i2s_audio - i2s_comm_fmt: lsb + i2s_comm_fmt: msb # Experimental - It was 'lsb' until v2024.12.12 dac_type: external mode: mono ... From ae87f025a33d7c036ec29895ac6e986da6a6576e Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 23 Dec 2024 23:28:41 +0000 Subject: [PATCH 004/109] Bump version to 2024.12.13 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index a31cabd..a829487 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.12 +2024.12.13 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index d4b581e..159f102 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.12 +version: 2024.12.13 From c4b2b8917ff0b99dc8678d027d6bbe6b8c7fe32a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:17:00 +0100 Subject: [PATCH 005/109] Consider disconnected if wifi is disconnected Trying to detect a disconnection earlier. --- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index 5735035..56d72da 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -191,7 +191,8 @@ script: } // Toggle relay if corresponding button action is enabled - const bool api_disconnected = not global_api_server->is_connected(); + const bool api_disconnected = !global_api_server->is_connected() or + !global_wifi_component->is_connected(); std::string select_state; bool toggle_relay = false; if (api_disconnected) { From a44e486411f957a5ace8774f9fa3a1f051539d5a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 01:23:29 +0100 Subject: [PATCH 006/109] Add Id to Wi-Fi component --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 1 + ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 75bfc76..487d003 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -208,5 +208,6 @@ time: web_server: wifi: + id: wifi_component ap: ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index 56d72da..afed401 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -192,7 +192,7 @@ script: // Toggle relay if corresponding button action is enabled const bool api_disconnected = !global_api_server->is_connected() or - !global_wifi_component->is_connected(); + !wifi_component->is_connected(); std::string select_state; bool toggle_relay = false; if (api_disconnected) { From 269ba89bd3100a7d3b68dbaf958e3eadad1fd632 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:49:14 +0100 Subject: [PATCH 007/109] New LED mapping for US 3-Gang Partially solves #67 --- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 3b20c0b..148736d 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -644,8 +644,8 @@ light: <<: *light_partition_relays segments: - id: light_full - from: 17 - to: 18 + from: 16 + to: 17 - id: light_us_rl_3_3_right name: Light - Relay 3 of 3 (right) <<: *light_partition_relays From 9fec812b6643f313437a6130f305113ec634695e Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:59:54 +0100 Subject: [PATCH 008/109] New LED mapping for 4-Gang US model --- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 148736d..4242d50 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -658,8 +658,8 @@ light: <<: *light_partition_relays segments: - id: light_full - from: 12 - to: 12 + from: 23 + to: 24 - id: light_us_rl_1_4_right name: Light - Relay 1 of 4 (right) <<: *light_partition_relays @@ -667,48 +667,51 @@ light: - id: light_full from: 31 to: 31 + - id: light_full + from: 0 + to: 0 - id: light_us_rl_2_4_left name: Light - Relay 2 of 4 (left) <<: *light_partition_relays segments: - id: light_full - from: 24 - to: 24 + from: 21 + to: 22 - id: light_us_rl_2_4_right name: Light - Relay 2 of 4 (right) <<: *light_partition_relays segments: - id: light_full - from: 2 + from: 1 to: 2 - id: light_us_rl_3_4_left name: Light - Relay 3 of 4 (left) <<: *light_partition_relays segments: - id: light_full - from: 21 - to: 21 + from: 17 + to: 18 - id: light_us_rl_3_4_right name: Light - Relay 3 of 4 (right) <<: *light_partition_relays segments: - id: light_full - from: 4 - to: 4 + from: 5 + to: 6 - id: light_us_rl_4_4_left name: Light - Relay 4 of 4 (left) <<: *light_partition_relays segments: - id: light_full - from: 19 - to: 19 + from: 15 + to: 16 - id: light_us_rl_4_4_right name: Light - Relay 4 of 4 (right) <<: *light_partition_relays segments: - id: light_full from: 7 - to: 7 + to: 8 script: - id: !extend boot_initialize From f258b8f78344064b0f59388e17e24f4afc5aa0c2 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 24 Dec 2024 09:06:47 +0000 Subject: [PATCH 009/109] Bump version to 2024.12.14 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index a829487..334818b 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.13 +2024.12.14 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 159f102..dd672ef 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.13 +version: 2024.12.14 From 695cca07a069e9aa835439bdf30e0bf5672c4faf Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 10:32:31 +0100 Subject: [PATCH 010/109] Add ESPHome Version sensor And renames the TX Firmware, which resolves #66 --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index ac461ef..106f6ea 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -167,8 +167,12 @@ select: - lambda: tx_ultimate->set_gang_count(static_cast(i)+1); text_sensor: + - id: esphome_fw_version + platform: version + name: "ESPHome Version" + - id: tx_fw_version - name: Firmware version + name: TX Ultimate Easy Firmware Version platform: template entity_category: diagnostic icon: mdi:tag-text-outline From 37b2e93896d4ea68c9fa9e164be14afcaedd8c5d Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:17:35 +0100 Subject: [PATCH 011/109] Sensor is diagnostic --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 106f6ea..bc06e54 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -168,8 +168,10 @@ select: text_sensor: - id: esphome_fw_version + name: ESPHome Version platform: version - name: "ESPHome Version" + entity_category: diagnostic + internal: false - id: tx_fw_version name: TX Ultimate Easy Firmware Version From 2aa036dc0ee089490c4794d13b943613400cd0da Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 24 Dec 2024 10:42:07 +0000 Subject: [PATCH 012/109] Bump version to 2024.12.15 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 334818b..626b42d 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.14 +2024.12.15 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index dd672ef..2d76bbc 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.14 +version: 2024.12.15 From 7a5a53784770b32ae09828be4b0f8f4d43dd4baf Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:57:03 +0100 Subject: [PATCH 013/109] Fix swipe log messages --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 21 ++++++++++++- ...X-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 30 +++++++++---------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index bc06e54..fb46397 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -75,6 +75,17 @@ esphome: then: - script.execute: boot_done +globals: + - id: is_us_model + type: bool + restore_value: true + initial_value: 'false' + + - id: gang_count + type: uint8_t + restore_value: true + initial_value: '0' + improv_serial: id: serial_improv @@ -146,6 +157,11 @@ select: entity_category: config disabled_by_default: false icon: mdi:tablet-cellphone + on_value: + then: + - lambda: |- + id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}"); + ESP_LOGI("core", "New model selected: %s", id(is_us_model) ? "US" : "EU"); - id: sl_tx_model_gang name: Model (Gang) @@ -164,7 +180,10 @@ select: icon: mdi:dip-switch on_value: then: - - lambda: tx_ultimate->set_gang_count(static_cast(i)+1); + - lambda: |- + id(gang_count) = static_cast(i) + 1; + ESP_LOGI("core", "New model selected: %" PRIu8 "-%s", id(gang_count), id(gang_count) > 1 ? "Gangs" : "Gang"); + tx_ultimate->set_gang_count(id(gang_count)); text_sensor: - id: esphome_fw_version diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index def7a97..1bada38 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -358,9 +358,9 @@ tx_ultimate_easy: - lambda: |- const uint8_t touch_position = static_cast(touch.x); if (touch_position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range - ESP_LOGE("tx_ultimate_easy", "Invalid long-touch position: %" PRIu8, touch_position); + ESP_LOGE("core_hw_touch", "Invalid long-touch position: %" PRIu8, touch_position); } else { - ESP_LOGI("tx_ultimate_easy", "Long-touch released at position %" PRIu8, touch_position); + ESP_LOGI("core_hw_touch", "Long-touch released at position %" PRIu8, touch_position); } on_multi_touch_release: @@ -373,21 +373,21 @@ tx_ultimate_easy: type: multi_touch action: release position: !lambda return touch.x; - - lambda: ESP_LOGI("tx_ultimate_easy", "Multi-touch released"); + - lambda: ESP_LOGI("core_hw_touch", "Multi-touch released"); - script.execute: touch_on_multi_touch_release on_press: - lambda: |- const uint8_t position = static_cast(touch.x); if (position > ${TOUCH_POSITION_MAX_VALUE}) { // Check for valid range - ESP_LOGE("tx_ultimate_easy", "Invalid touch position: %" PRIu8, position); + ESP_LOGE("core_hw_touch", "Invalid touch position: %" PRIu8, position); } else { - ESP_LOGI("tx_ultimate_easy", "Pressed at position %" PRIu8, position); + ESP_LOGI("core_hw_touch", "Pressed at position %" PRIu8, position); touch_on_press->execute(static_cast(touch.button), position); } on_release: - - lambda: ESP_LOGI("tx_ultimate_easy", "Released"); + - lambda: ESP_LOGI("core_hw_touch", "Released"); - script.execute: touch_on_release on_swipe_left: @@ -399,12 +399,12 @@ tx_ultimate_easy: domain: touch type: swipe action: !lambda |- - return sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" ? "left" : "down"; + return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "left" : "down"; swipe-direction: !lambda |- - return sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" ? "left" : "down"; + return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "left" : "down"; position: !lambda return touch.x; - lambda: |- - ESP_LOGI("tx_ultimate_easy", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" + ESP_LOGI("core_hw_touch", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "left" : "down"); - script.execute: touch_swipe_left @@ -418,21 +418,21 @@ tx_ultimate_easy: domain: touch type: swipe action: !lambda |- - return sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" ? "right" : "up"; + return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "right" : "up"; swipe-direction: !lambda |- - return sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" ? "right" : "up"; + return sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "right" : "up"; position: !lambda return touch.x; - lambda: |- - ESP_LOGI("tx_ultimate_easy", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}" + ESP_LOGI("core_hw_touch", "Swipe %s", sl_tx_model_format->state == "${TX_MODEL_FORMAT_EU_TEXT}" ? "right" : "up"); - script.execute: touch_swipe_right on_touch_event: - lambda: |- - ESP_LOGD("tx_ultimate_easy", "Touch event:"); - ESP_LOGD("tx_ultimate_easy", " State: %i (%s)", touch.state, touch.state_str.c_str()); - ESP_LOGD("tx_ultimate_easy", " Position: %i", touch.x); + ESP_LOGD("core_hw_touch", "Touch event:"); + ESP_LOGD("core_hw_touch", " State: %i (%s)", touch.state, touch.state_str.c_str()); + ESP_LOGD("core_hw_touch", " Position: %i", touch.x); uart: - id: uart_touch From e8470f56e44695468235aa9ff0584b335165f92a Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 24 Dec 2024 11:02:55 +0000 Subject: [PATCH 014/109] Bump version to 2024.12.16 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 626b42d..79bed18 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.15 +2024.12.16 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 2d76bbc..735400f 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.15 +version: 2024.12.16 From 44b3586a170e74013ee10f055e8dc7694047ee93 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 24 Dec 2024 13:46:33 +0000 Subject: [PATCH 015/109] Bump version to 2024.12.17 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 79bed18..569d179 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.16 +2024.12.17 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 735400f..af59191 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.16 +version: 2024.12.17 From 403cdce2b587641c82cd7d8ed4f52246964d5c69 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 24 Dec 2024 23:31:50 +0100 Subject: [PATCH 016/109] Expose relay-indicator LEDs The lights will be available on Home Assistant, so users will be able to set it's color and brightness, then this will be used when the relay turn on-off as the indicator for the relay status. Resolves #57 --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 30 +- ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 25 +- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 356 +------------- ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 450 +++++++++++++++--- ...Ultimate-Easy-ESPHome_core_hw_speaker.yaml | 6 +- ...X-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 31 +- 6 files changed, 470 insertions(+), 428 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 235ac7c..a05fdb3 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -41,6 +41,15 @@ api: then: - script.execute: publish_device_info +binary_sensor: + - id: bs_pending_restart + name: Pending Restart Status + internal: false + disabled_by_default: false + platform: template + entity_category: diagnostic + device_class: problem + button: - id: bt_restart name: Restart @@ -97,7 +106,7 @@ ota: psram: mode: octal - speed: 40MHz + speed: 80MHz script: - id: api_send_ha_event_boot @@ -130,11 +139,24 @@ script: - script.execute: id: api_send_ha_event_boot type: start + - wait_until: + condition: + - lambda: return sl_tx_model_format->active_index().has_value(); + - lambda: return sl_tx_model_gang->active_index().has_value(); + - lambda: |- + id(is_us_model) = (sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}"); + id(gang_count) = sl_tx_model_gang->active_index().value() + 1; + if (id(gang_count) < 1 || id(gang_count) > 4) { + ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, id(gang_count)); + } - id: boot_sequence mode: restart then: - script.execute: publish_device_info + - binary_sensor.template.publish: + id: bs_pending_restart + state: false - id: publish_device_info mode: restart @@ -159,6 +181,9 @@ select: icon: mdi:tablet-cellphone on_value: then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true - lambda: |- id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}"); ESP_LOGI("core", "New model selected: %s", id(is_us_model) ? "US" : "EU"); @@ -180,6 +205,9 @@ select: icon: mdi:dip-switch on_value: then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true - lambda: |- id(gang_count) = static_cast(i) + 1; ESP_LOGI("core", "New model selected: %" PRIu8 "-%s", id(gang_count), id(gang_count) > 1 ? "Gangs" : "Gang"); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index b7be303..de16ddc 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -86,28 +86,19 @@ script: - id: boot_initialize_buttons mode: restart then: - - wait_until: - condition: - - lambda: return sl_tx_model_gang->active_index().has_value(); - lambda: |- - const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? - (sl_tx_model_gang->active_index().value() + 1) : 0; - if (num_gangs < 1 || num_gangs > 4) { - ESP_LOGE("core_hw_buttons", "Invalid number of gangs: %" PRIu8, num_gangs); - return; - } bs_button_1->publish_state(false); - bs_button_1->set_internal(num_gangs < 1); - sl_button_1_action->set_internal(num_gangs < 1); + bs_button_1->set_internal(id(gang_count) < 1); + sl_button_1_action->set_internal(id(gang_count) < 1); bs_button_2->publish_state(false); - bs_button_2->set_internal(num_gangs < 2); - sl_button_2_action->set_internal(num_gangs < 2); + bs_button_2->set_internal(id(gang_count) < 2); + sl_button_2_action->set_internal(id(gang_count) < 2); bs_button_3->publish_state(false); - bs_button_3->set_internal(num_gangs < 3); - sl_button_3_action->set_internal(num_gangs < 3); + bs_button_3->set_internal(id(gang_count) < 3); + sl_button_3_action->set_internal(id(gang_count) < 3); bs_button_4->publish_state(false); - bs_button_4->set_internal(num_gangs < 4); - sl_button_4_action->set_internal(num_gangs < 4); + bs_button_4->set_internal(id(gang_count) < 4); + sl_button_4_action->set_internal(id(gang_count) < 4); - id: button_action mode: parallel diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 4242d50..c3c4a59 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -28,7 +28,6 @@ substitutions: LIGHT_FULL_RESTORE_MODE: RESTORE_DEFAULT_OFF LIGHT_SIDES_RESTORE_MODE: RESTORE_DEFAULT_OFF LIGHT_INDIVIDUAL_RESTORE_MODE: RESTORE_DEFAULT_OFF - LIGHT_RELAYS_RESTORE_MODE: RESTORE_DEFAULT_OFF globals: - id: gb_lights_1 @@ -418,334 +417,27 @@ light: from: 31 to: 31 - # These lights are used to indicate relay's statuses - - &light_partition_relays - id: light_eu_rl_1_1_bottom - name: Light - Relay 1 of 1 (bottom) - platform: partition - internal: true - default_transition_length: ${default_transition_length} - restore_mode: ${LIGHT_RELAYS_RESTORE_MODE} - segments: - - id: light_full - from: 9 - to: 9 - - id: light_eu_rl_1_1_top - name: Light - Relay 1 of 1 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 23 - to: 23 - - id: light_eu_rl_1_2_bottom - name: Light - Relay 1 of 2 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 11 - to: 11 - - id: light_eu_rl_1_2_top - name: Light - Relay 1 of 2 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 21 - to: 21 - - id: light_eu_rl_2_2_bottom - name: Light - Relay 2 of 2 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 7 - to: 7 - - id: light_eu_rl_2_2_top - name: Light - Relay 2 of 2 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 25 - to: 25 - - id: light_eu_rl_1_3_bottom - name: Light - Relay 1 of 3 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 12 - to: 12 - - id: light_eu_rl_1_3_top - name: Light - Relay 1 of 3 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 20 - to: 20 - - id: light_eu_rl_2_3_bottom - name: Light - Relay 2 of 3 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 9 - to: 9 - - id: light_eu_rl_2_3_top - name: Light - Relay 2 of 3 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 23 - to: 23 - - id: light_eu_rl_3_3_bottom - name: Light - Relay 3 of 3 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 6 - to: 6 - - id: light_eu_rl_3_3_top - name: Light - Relay 3 of 3 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 26 - to: 26 - - id: light_eu_rl_1_4_bottom - name: Light - Relay 1 of 4 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 12 - to: 12 - - id: light_eu_rl_1_4_top - name: Light - Relay 1 of 4 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 20 - to: 20 - - id: light_eu_rl_2_4_bottom - name: Light - Relay 2 of 4 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 10 - to: 10 - - id: light_eu_rl_2_4_top - name: Light - Relay 2 of 4 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 22 - to: 22 - - id: light_eu_rl_3_4_bottom - name: Light - Relay 3 of 4 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 8 - to: 8 - - id: light_eu_rl_3_4_top - name: Light - Relay 3 of 4 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 24 - to: 24 - - id: light_eu_rl_4_4_bottom - name: Light - Relay 4 of 4 (bottom) - <<: *light_partition_relays - segments: - - id: light_full - from: 6 - to: 6 - - id: light_eu_rl_4_4_top - name: Light - Relay 4 of 4 (top) - <<: *light_partition_relays - segments: - - id: light_full - from: 26 - to: 26 - - id: light_us_rl_1_1_left - name: Light - Relay 1 of 1 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 15 - to: 24 - - id: light_us_rl_1_1_right - name: Light - Relay 1 of 1 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 31 - to: 31 - - id: light_full - from: 0 - to: 8 - - id: light_us_rl_1_2_left - name: Light - Relay 1 of 2 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 20 - to: 24 - - id: light_us_rl_1_2_right - name: Light - Relay 1 of 2 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 31 - to: 31 - - id: light_full - from: 0 - to: 3 - - id: light_us_rl_2_2_left - name: Light - Relay 2 of 2 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 15 - to: 19 - - id: light_us_rl_2_2_right - name: Light - Relay 2 of 2 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 4 - to: 8 - - id: light_us_rl_1_3_left - name: Light - Relay 1 of 3 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 22 - to: 23 - - id: light_us_rl_1_3_right - name: Light - Relay 1 of 3 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 0 - to: 1 - - id: light_us_rl_2_3_left - name: Light - Relay 2 of 3 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 19 - to: 20 - - id: light_us_rl_2_3_right - name: Light - Relay 2 of 3 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 3 - to: 4 - - id: light_us_rl_3_3_left - name: Light - Relay 3 of 3 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 16 - to: 17 - - id: light_us_rl_3_3_right - name: Light - Relay 3 of 3 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 6 - to: 7 - - id: light_us_rl_1_4_left - name: Light - Relay 1 of 4 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 23 - to: 24 - - id: light_us_rl_1_4_right - name: Light - Relay 1 of 4 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 31 - to: 31 - - id: light_full - from: 0 - to: 0 - - id: light_us_rl_2_4_left - name: Light - Relay 2 of 4 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 21 - to: 22 - - id: light_us_rl_2_4_right - name: Light - Relay 2 of 4 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 1 - to: 2 - - id: light_us_rl_3_4_left - name: Light - Relay 3 of 4 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 17 - to: 18 - - id: light_us_rl_3_4_right - name: Light - Relay 3 of 4 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 5 - to: 6 - - id: light_us_rl_4_4_left - name: Light - Relay 4 of 4 (left) - <<: *light_partition_relays - segments: - - id: light_full - from: 15 - to: 16 - - id: light_us_rl_4_4_right - name: Light - Relay 4 of 4 (right) - <<: *light_partition_relays - segments: - - id: light_full - from: 7 - to: 8 - script: - id: !extend boot_initialize then: - - wait_until: - condition: - - lambda: return sl_tx_model_format->active_index().has_value(); - - lambda: return sl_tx_model_gang->active_index().has_value(); - lambda: |- - const bool is_model_us = sl_tx_model_format->active_index().has_value() and - sl_tx_model_format->active_index().value() == 1; - const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? - (sl_tx_model_gang->active_index().value() + 1) : 0; - if (num_gangs < 1 || num_gangs > 4) { - ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, num_gangs); - return; - } - light_28->set_internal(!is_model_us); - light_29->set_internal(!is_model_us); - light_30->set_internal(!is_model_us); - light_31->set_internal(!is_model_us); - light_eu->set_internal(is_model_us); - light_eu_bottom->set_internal(is_model_us); - light_eu_left->set_internal(is_model_us); - light_eu_right->set_internal(is_model_us); - light_eu_top->set_internal(is_model_us); - light_us->set_internal(!is_model_us); - light_us_bottom->set_internal(!is_model_us); - light_us_left->set_internal(!is_model_us); - light_us_right->set_internal(!is_model_us); - light_us_top->set_internal(!is_model_us); - switch (num_gangs) { + light_28->set_internal(!id(is_us_model)); + light_29->set_internal(!id(is_us_model)); + light_30->set_internal(!id(is_us_model)); + light_31->set_internal(!id(is_us_model)); + light_eu->set_internal(id(is_us_model)); + light_eu_bottom->set_internal(id(is_us_model)); + light_eu_left->set_internal(id(is_us_model)); + light_eu_right->set_internal(id(is_us_model)); + light_eu_top->set_internal(id(is_us_model)); + light_us->set_internal(!id(is_us_model)); + light_us_bottom->set_internal(!id(is_us_model)); + light_us_left->set_internal(!id(is_us_model)); + light_us_right->set_internal(!id(is_us_model)); + light_us_top->set_internal(!id(is_us_model)); + switch (id(gang_count)) { case 1: // 1 Gang - if (is_model_us) { + if (id(is_us_model)) { id(gb_lights_1) = { light_us_rl_1_1_left }; id(gb_lights_2) = { light_us_rl_1_1_right }; } else { @@ -754,7 +446,7 @@ script: } break; case 2: // 2 Gang - if (is_model_us) { + if (id(is_us_model)) { id(gb_lights_1) = { light_us_rl_1_2_left, light_us_rl_2_2_left }; id(gb_lights_2) = { light_us_rl_1_2_right, light_us_rl_2_2_right }; } else { @@ -763,7 +455,7 @@ script: } break; case 3: // 3 Gang - if (is_model_us) { + if (id(is_us_model)) { id(gb_lights_1) = { light_us_rl_1_3_left, light_us_rl_2_3_left, light_us_rl_3_3_left }; id(gb_lights_2) = { light_us_rl_1_3_right, light_us_rl_2_3_right, light_us_rl_3_3_right }; } else { @@ -772,7 +464,7 @@ script: } break; case 4: // 4 Gang - if (is_model_us) { + if (id(is_us_model)) { id(gb_lights_1) = { light_us_rl_1_4_left, light_us_rl_2_4_left, light_us_rl_3_4_left, light_us_rl_4_4_left }; id(gb_lights_2) = { light_us_rl_1_4_right, light_us_rl_2_4_right, @@ -798,10 +490,12 @@ script: static const uint32_t LIGHT_TRANSITION_TURN_OFF = ${LIGHT_TRANSITION_TURN_OFF}; static const uint8_t LIGHT_BRIGHTNESS_TURN_ON = ${LIGHT_BRIGHTNESS_TURN_ON}; - const bool is_model_us = sl_tx_model_format->active_index().has_value() and - sl_tx_model_format->active_index().value() == 1; - const std::string light_mode_group_1 = is_model_us ? "${LIGHT_MODE_LEFT_TEXT}" : "${LIGHT_MODE_BOTTOM_TEXT}"; - const std::string light_mode_group_2 = is_model_us ? "${LIGHT_MODE_RIGHT_TEXT}" : "${LIGHT_MODE_TOP_TEXT}"; + const std::string light_mode_group_1 = id(is_us_model) + ? "${LIGHT_MODE_LEFT_TEXT}" + : "${LIGHT_MODE_BOTTOM_TEXT}"; + const std::string light_mode_group_2 = id(is_us_model) + ? "${LIGHT_MODE_RIGHT_TEXT}" + : "${LIGHT_MODE_TOP_TEXT}"; switch (light_group) { case 1: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index afed401..e558940 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -15,7 +15,10 @@ substitutions: RELAY_MODE_TEXT_SWITCH: "Switch" RELAY_MODE_TEXT_LIGHT: "Light" RELAY_MODE_TEXT_NOT_USED: "Not in use" + RELAY_RESTORE_MODE: RESTORE_DEFAULT_OFF + LIGHT_RELAYS_RESTORE_MODE: RESTORE_DEFAULT_OFF + globals: - id: boot_initialization_relays @@ -103,19 +106,312 @@ light: then: - switch.turn_off: sw_relay_4 + # These lights are used to indicate relay's statuses + - &light_partition_relays + id: light_eu_rl_1_1_bottom + name: Light - Relay 1 of 1 (bottom) + platform: partition + internal: true + disabled_by_default: true + default_transition_length: ${default_transition_length} + restore_mode: ${LIGHT_RELAYS_RESTORE_MODE} + segments: + - id: light_full + from: 9 + to: 9 + - id: light_eu_rl_1_1_top + name: Light - Relay 1 of 1 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 23 + to: 23 + - id: light_eu_rl_1_2_bottom + name: Light - Relay 1 of 2 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 11 + to: 11 + - id: light_eu_rl_1_2_top + name: Light - Relay 1 of 2 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 21 + to: 21 + - id: light_eu_rl_2_2_bottom + name: Light - Relay 2 of 2 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 7 + to: 7 + - id: light_eu_rl_2_2_top + name: Light - Relay 2 of 2 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 25 + to: 25 + - id: light_eu_rl_1_3_bottom + name: Light - Relay 1 of 3 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 12 + to: 12 + - id: light_eu_rl_1_3_top + name: Light - Relay 1 of 3 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 20 + to: 20 + - id: light_eu_rl_2_3_bottom + name: Light - Relay 2 of 3 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 9 + to: 9 + - id: light_eu_rl_2_3_top + name: Light - Relay 2 of 3 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 23 + to: 23 + - id: light_eu_rl_3_3_bottom + name: Light - Relay 3 of 3 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 6 + to: 6 + - id: light_eu_rl_3_3_top + name: Light - Relay 3 of 3 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 26 + to: 26 + - id: light_eu_rl_1_4_bottom + name: Light - Relay 1 of 4 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 12 + to: 12 + - id: light_eu_rl_1_4_top + name: Light - Relay 1 of 4 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 20 + to: 20 + - id: light_eu_rl_2_4_bottom + name: Light - Relay 2 of 4 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 10 + to: 10 + - id: light_eu_rl_2_4_top + name: Light - Relay 2 of 4 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 22 + to: 22 + - id: light_eu_rl_3_4_bottom + name: Light - Relay 3 of 4 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 8 + to: 8 + - id: light_eu_rl_3_4_top + name: Light - Relay 3 of 4 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 24 + to: 24 + - id: light_eu_rl_4_4_bottom + name: Light - Relay 4 of 4 (bottom) + <<: *light_partition_relays + segments: + - id: light_full + from: 6 + to: 6 + - id: light_eu_rl_4_4_top + name: Light - Relay 4 of 4 (top) + <<: *light_partition_relays + segments: + - id: light_full + from: 26 + to: 26 + - id: light_us_rl_1_1_left + name: Light - Relay 1 of 1 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 15 + to: 24 + - id: light_us_rl_1_1_right + name: Light - Relay 1 of 1 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 31 + to: 31 + - id: light_full + from: 0 + to: 8 + - id: light_us_rl_1_2_left + name: Light - Relay 1 of 2 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 20 + to: 24 + - id: light_us_rl_1_2_right + name: Light - Relay 1 of 2 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 31 + to: 31 + - id: light_full + from: 0 + to: 3 + - id: light_us_rl_2_2_left + name: Light - Relay 2 of 2 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 15 + to: 19 + - id: light_us_rl_2_2_right + name: Light - Relay 2 of 2 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 4 + to: 8 + - id: light_us_rl_1_3_left + name: Light - Relay 1 of 3 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 22 + to: 23 + - id: light_us_rl_1_3_right + name: Light - Relay 1 of 3 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 0 + to: 1 + - id: light_us_rl_2_3_left + name: Light - Relay 2 of 3 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 19 + to: 20 + - id: light_us_rl_2_3_right + name: Light - Relay 2 of 3 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 3 + to: 4 + - id: light_us_rl_3_3_left + name: Light - Relay 3 of 3 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 16 + to: 17 + - id: light_us_rl_3_3_right + name: Light - Relay 3 of 3 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 6 + to: 7 + - id: light_us_rl_1_4_left + name: Light - Relay 1 of 4 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 23 + to: 24 + - id: light_us_rl_1_4_right + name: Light - Relay 1 of 4 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 31 + to: 31 + - id: light_full + from: 0 + to: 0 + - id: light_us_rl_2_4_left + name: Light - Relay 2 of 4 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 21 + to: 22 + - id: light_us_rl_2_4_right + name: Light - Relay 2 of 4 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 1 + to: 2 + - id: light_us_rl_3_4_left + name: Light - Relay 3 of 4 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 17 + to: 18 + - id: light_us_rl_3_4_right + name: Light - Relay 3 of 4 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 5 + to: 6 + - id: light_us_rl_4_4_left + name: Light - Relay 4 of 4 (left) + <<: *light_partition_relays + segments: + - id: light_full + from: 15 + to: 16 + - id: light_us_rl_4_4_right + name: Light - Relay 4 of 4 (right) + <<: *light_partition_relays + segments: + - id: light_full + from: 7 + to: 8 + output: - id: output_relay_1 platform: gpio pin: GPIO18 - - id: output_relay_2 platform: gpio pin: GPIO17 - - id: output_relay_3 platform: gpio pin: GPIO27 - - id: output_relay_4 platform: gpio pin: GPIO23 @@ -128,31 +424,19 @@ script: - id: boot_initialize_relays mode: restart then: - - wait_until: - condition: - - lambda: return sl_tx_model_format->active_index().has_value(); - - lambda: return sl_tx_model_gang->active_index().has_value(); - lambda: |- - const bool is_model_us = sl_tx_model_format->active_index().has_value() and - sl_tx_model_format->active_index().value() == 1; - const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? - (sl_tx_model_gang->active_index().value() + 1) : 0; - if (num_gangs < 1 || num_gangs > 4) { - ESP_LOGE("core_hw_relays", "Invalid number of gangs: %" PRIu8, num_gangs); - return; - } - sl_relay_1_mode->set_internal(num_gangs < 1); - sl_relay_1_light_mode_eu->set_internal(is_model_us or num_gangs < 1); - sl_relay_1_light_mode_us->set_internal(!is_model_us or num_gangs < 1); - sl_relay_2_mode->set_internal(num_gangs < 2); - sl_relay_2_light_mode_eu->set_internal(is_model_us or num_gangs < 2); - sl_relay_2_light_mode_us->set_internal(!is_model_us or num_gangs < 2); - sl_relay_3_mode->set_internal(num_gangs < 3); - sl_relay_3_light_mode_eu->set_internal(is_model_us or num_gangs < 3); - sl_relay_3_light_mode_us->set_internal(!is_model_us or num_gangs < 3); - sl_relay_4_mode->set_internal(num_gangs < 4); - sl_relay_4_light_mode_eu->set_internal(is_model_us or num_gangs < 4); - sl_relay_4_light_mode_us->set_internal(!is_model_us or num_gangs < 4); + sl_relay_1_mode->set_internal(id(gang_count) < 1); + sl_relay_1_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 1); + sl_relay_1_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 1); + sl_relay_2_mode->set_internal(id(gang_count) < 2); + sl_relay_2_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 2); + sl_relay_2_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 2); + sl_relay_3_mode->set_internal(id(gang_count) < 3); + sl_relay_3_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 3); + sl_relay_3_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 3); + sl_relay_4_mode->set_internal(id(gang_count) < 4); + sl_relay_4_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 4); + sl_relay_4_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 4); auto relay_mode_index = sl_relay_1_mode->active_index(); if (relay_mode_index.has_value()) { light_output_1->set_internal(false or relay_mode_index.value() != 1); @@ -160,19 +444,60 @@ script: } relay_mode_index = sl_relay_2_mode->active_index(); if (relay_mode_index.has_value()) { - light_output_2->set_internal(num_gangs < 2 or relay_mode_index.value() != 1); - sw_relay_2->set_internal(num_gangs < 2 or relay_mode_index.value() != 0); + light_output_2->set_internal(id(gang_count) < 2 or relay_mode_index.value() != 1); + sw_relay_2->set_internal(id(gang_count) < 2 or relay_mode_index.value() != 0); } relay_mode_index = sl_relay_3_mode->active_index(); if (relay_mode_index.has_value()) { - light_output_3->set_internal(num_gangs < 3 or relay_mode_index.value() != 1); - sw_relay_3->set_internal(num_gangs < 3 or relay_mode_index.value() != 0); + light_output_3->set_internal(id(gang_count) < 3 or relay_mode_index.value() != 1); + sw_relay_3->set_internal(id(gang_count) < 3 or relay_mode_index.value() != 0); } relay_mode_index = sl_relay_4_mode->active_index(); if (relay_mode_index.has_value()) { - light_output_4->set_internal(num_gangs < 4 or relay_mode_index.value() != 1); - sw_relay_4->set_internal(num_gangs < 4 or relay_mode_index.value() != 0); + light_output_4->set_internal(id(gang_count) < 4 or relay_mode_index.value() != 1); + sw_relay_4->set_internal(id(gang_count) < 4 or relay_mode_index.value() != 0); } + const bool set_internal = not sw_expose_relays_leds_to_ha->state; + light_eu_rl_1_1_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); + light_eu_rl_1_1_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); + light_eu_rl_1_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_1_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_2_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_2_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_1_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_1_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_2_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_2_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_3_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_3_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_1_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_1_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_2_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_2_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_3_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_3_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_4_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_4_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_us_rl_1_1_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); + light_us_rl_1_1_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); + light_us_rl_1_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_1_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_2_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_2_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_1_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_1_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_2_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_2_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_3_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_3_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_1_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_1_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_2_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_2_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_3_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_3_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_4_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_4_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); id(boot_initialization_relays) = true; - id: !extend button_click_event @@ -247,28 +572,20 @@ script: mode: restart then: - script.wait: boot_initialize_relays - - wait_until: - condition: - - lambda: return id(boot_initialization_relays); - lambda: |- - const bool is_model_us = sl_tx_model_format->active_index().has_value() and - sl_tx_model_format->active_index().value() == 1; - const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) - ? (sl_tx_model_gang->active_index().value() + 1) - : 0; - - if (num_gangs < 1 || num_gangs > 4) { - ESP_LOGE("core_hw_relays", "Invalid number of gangs: %" PRIu8, num_gangs); + if (not id(boot_initialization_relays)) { + ESP_LOGW("core_hw_relays", "Relays not initialized yet"); + if (not boot_initialize_relays->is_running()) + boot_initialize_relays->execute(); return; } - - for (uint8_t i = 0; i < num_gangs; i++) { + for (uint8_t i = 0; i < id(gang_count); i++) { bool relay_state = false; std::string light_mode; - const std::string light_mode_group_1 = is_model_us + const std::string light_mode_group_1 = id(is_us_model) ? "${LIGHT_MODE_LEFT_TEXT}" : "${LIGHT_MODE_BOTTOM_TEXT}"; - const std::string light_mode_group_2 = is_model_us + const std::string light_mode_group_2 = id(is_us_model) ? "${LIGHT_MODE_RIGHT_TEXT}" : "${LIGHT_MODE_TOP_TEXT}"; @@ -276,25 +593,25 @@ script: switch (i) { case 0: relay_state = id(sw_relay_1).state; - light_mode = is_model_us + light_mode = id(is_us_model) ? id(sl_relay_1_light_mode_us)->state : id(sl_relay_1_light_mode_eu)->state; break; case 1: relay_state = id(sw_relay_2).state; - light_mode = is_model_us + light_mode = id(is_us_model) ? id(sl_relay_2_light_mode_us)->state : id(sl_relay_2_light_mode_eu)->state; break; case 2: relay_state = id(sw_relay_3).state; - light_mode = is_model_us + light_mode = id(is_us_model) ? id(sl_relay_3_light_mode_us)->state : id(sl_relay_3_light_mode_eu)->state; break; case 3: relay_state = id(sw_relay_4).state; - light_mode = is_model_us + light_mode = id(is_us_model) ? id(sl_relay_4_light_mode_us)->state : id(sl_relay_4_light_mode_eu)->state; break; @@ -333,20 +650,40 @@ select: entity_category: config disabled_by_default: false icon: mdi:dip-switch - + on_value: + then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true - id: sl_relay_2_mode name: Relay 2 display mode <<: *relay_select_mode_base - - id: sl_relay_3_mode name: Relay 3 display mode <<: *relay_select_mode_base - - id: sl_relay_4_mode name: Relay 4 display mode <<: *relay_select_mode_base switch: + - id: sw_expose_relays_leds_to_ha + name: Expose Relay's LEDs to Home Assistant + platform: template + restore_mode: RESTORE_DEFAULT_OFF + optimistic: true + internal: false + entity_category: config + on_turn_on: + then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true + on_turn_off: + then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true + - id: sw_relay_1 name: Relay 1 output: output_relay_1 @@ -369,7 +706,6 @@ switch: - light.is_on: light_output_1 then: - light.turn_off: light_output_1 - - id: sw_relay_2 name: Relay 2 output: output_relay_2 @@ -392,7 +728,6 @@ switch: - light.is_on: light_output_2 then: - light.turn_off: light_output_2 - - id: sw_relay_3 name: Relay 3 output: output_relay_3 @@ -415,7 +750,6 @@ switch: - light.is_on: light_output_3 then: - light.turn_off: light_output_3 - - id: sw_relay_4 name: Relay 4 output: output_relay_4 diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml index 2addc80..d206ea6 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome Core - Hardware - Speaker ##### +##### Purpose: ESPHome Core - Hardware - Media player ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### @@ -17,8 +17,8 @@ i2s_audio: i2s_lrclk_pin: GPIO4 media_player: - - id: mp_speaker - name: Speaker + - id: mp_media_player + name: Media Player internal: false platform: i2s_audio i2s_dout_pin: GPIO15 diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index 1bada38..1d204c9 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -256,13 +256,8 @@ script: - id: boot_initialize_touch_gang mode: restart then: - - wait_until: - condition: - - lambda: return sl_tx_model_gang->active_index().has_value(); - lambda: |- - const uint8_t num_gangs = (sl_tx_model_gang->active_index().has_value()) ? - (sl_tx_model_gang->active_index().value() + 1) : 0; - tx_ultimate->set_gang_count(num_gangs); + tx_ultimate->set_gang_count(id(gang_count)); bs_button_1_click_event->publish_state(false); bs_button_2_click_event->publish_state(false); bs_button_3_click_event->publish_state(false); @@ -275,18 +270,18 @@ script: bs_button_2_long_press_event->publish_state(false); bs_button_3_long_press_event->publish_state(false); bs_button_4_long_press_event->publish_state(false); - bs_button_1_click_event->set_internal(num_gangs < 1); - bs_button_2_click_event->set_internal(num_gangs < 2); - bs_button_3_click_event->set_internal(num_gangs < 3); - bs_button_4_click_event->set_internal(num_gangs < 4); - bs_button_1_double_click_event->set_internal(num_gangs < 1); - bs_button_2_double_click_event->set_internal(num_gangs < 2); - bs_button_3_double_click_event->set_internal(num_gangs < 3); - bs_button_4_double_click_event->set_internal(num_gangs < 4); - bs_button_1_long_press_event->set_internal(num_gangs < 1); - bs_button_2_long_press_event->set_internal(num_gangs < 2); - bs_button_3_long_press_event->set_internal(num_gangs < 3); - bs_button_4_long_press_event->set_internal(num_gangs < 4); + bs_button_1_click_event->set_internal(id(gang_count) < 1); + bs_button_2_click_event->set_internal(id(gang_count) < 2); + bs_button_3_click_event->set_internal(id(gang_count) < 3); + bs_button_4_click_event->set_internal(id(gang_count) < 4); + bs_button_1_double_click_event->set_internal(id(gang_count) < 1); + bs_button_2_double_click_event->set_internal(id(gang_count) < 2); + bs_button_3_double_click_event->set_internal(id(gang_count) < 3); + bs_button_4_double_click_event->set_internal(id(gang_count) < 4); + bs_button_1_long_press_event->set_internal(id(gang_count) < 1); + bs_button_2_long_press_event->set_internal(id(gang_count) < 2); + bs_button_3_long_press_event->set_internal(id(gang_count) < 3); + bs_button_4_long_press_event->set_internal(id(gang_count) < 4); - id: touch_on_multi_touch_release mode: restart From bcf4396c6fe738f2e5922f65560cb7058428c569 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Dec 2024 00:01:57 +0100 Subject: [PATCH 017/109] Split `boot_initialize_relays` script --- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 5 + ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 164 ++++++++++++------ 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index c3c4a59..b71944c 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -435,6 +435,11 @@ script: light_us_left->set_internal(!id(is_us_model)); light_us_right->set_internal(!id(is_us_model)); light_us_top->set_internal(!id(is_us_model)); + + // LED Group Assignment: + // - For US model: gb_lights_1 = left side LEDs, gb_lights_2 = right side LEDs + // - For EU model: gb_lights_1 = bottom LEDs, gb_lights_2 = top LEDs + // Gang configurations determine which LED segments are active switch (id(gang_count)) { case 1: // 1 Gang if (id(is_us_model)) { diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index e558940..5f47897 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -25,6 +25,18 @@ globals: type: bool restore_value: false initial_value: 'false' + - id: boot_initialization_relays_light_modes + type: bool + restore_value: false + initial_value: 'false' + - id: boot_initialization_relays_relay_leds + type: bool + restore_value: false + initial_value: 'false' + - id: boot_initialization_relays_relay_modes + type: bool + restore_value: false + initial_value: 'false' light: # These lights are used for the physical relays to be shown as lights @@ -422,21 +434,114 @@ script: - script.execute: boot_initialize_relays - id: boot_initialize_relays + mode: restart + then: + - script.execute: boot_initialize_relays_light_modes + - script.execute: boot_initialize_relays_relay_leds + - script.execute: boot_initialize_relays_relay_modes + - script.wait: boot_initialize_relays_light_modes + - script.wait: boot_initialize_relays_relay_leds + - script.wait: boot_initialize_relays_relay_modes + - wait_until: + condition: + - lambda: return id(boot_initialization_relays_light_modes); + - lambda: return id(boot_initialization_relays_relay_leds); + - lambda: return id(boot_initialization_relays_relay_modes); + - globals.set: + id: boot_initialization_relays + value: 'true' + + - id: boot_initialize_relays_light_modes mode: restart then: - lambda: |- - sl_relay_1_mode->set_internal(id(gang_count) < 1); + // EU light modes sl_relay_1_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 1); - sl_relay_1_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 1); - sl_relay_2_mode->set_internal(id(gang_count) < 2); sl_relay_2_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 2); - sl_relay_2_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 2); - sl_relay_3_mode->set_internal(id(gang_count) < 3); sl_relay_3_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 3); - sl_relay_3_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 3); - sl_relay_4_mode->set_internal(id(gang_count) < 4); sl_relay_4_light_mode_eu->set_internal(id(is_us_model) or id(gang_count) < 4); + + // US light modes + sl_relay_1_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 1); + sl_relay_2_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 2); + sl_relay_3_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 3); sl_relay_4_light_mode_us->set_internal(!id(is_us_model) or id(gang_count) < 4); + + // Set this section of initialization as completed + id(boot_initialization_relays_light_modes) = true; + + - id: boot_initialize_relays_relay_leds + mode: restart + then: + - lambda: |- + const bool set_internal = not sw_expose_relays_leds_to_ha->state; + + // EU model LEDs + // EU model - 1 Gang + light_eu_rl_1_1_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); + light_eu_rl_1_1_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); + // EU model - 2 Gang + light_eu_rl_1_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_1_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_2_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + light_eu_rl_2_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); + // EU model - 3 Gang + light_eu_rl_1_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_1_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_2_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_2_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_3_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + light_eu_rl_3_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); + // EU model - 4 Gang + light_eu_rl_1_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_1_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_2_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_2_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_3_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_3_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_4_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + light_eu_rl_4_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); + + // US model LEDs + // US model - 1 Gang + light_us_rl_1_1_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); + light_us_rl_1_1_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); + // US model - 2 Gang + light_us_rl_1_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_1_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_2_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + light_us_rl_2_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); + // US model - 3 Gang + light_us_rl_1_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_1_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_2_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_2_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_3_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + light_us_rl_3_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); + // US model - 4 Gang + light_us_rl_1_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_1_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_2_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_2_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_3_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_3_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_4_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + light_us_rl_4_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); + + // Set this section of initialization as completed + id(boot_initialization_relays_relay_leds) = true; + + - id: boot_initialize_relays_relay_modes + mode: restart + then: + - lambda: |- + // Set selector internal based on the model (num of relays) + sl_relay_1_mode->set_internal(id(gang_count) < 1); + sl_relay_2_mode->set_internal(id(gang_count) < 2); + sl_relay_3_mode->set_internal(id(gang_count) < 3); + sl_relay_4_mode->set_internal(id(gang_count) < 4); + + // Set indicator (either switch or light) visible on Home Assistant auto relay_mode_index = sl_relay_1_mode->active_index(); if (relay_mode_index.has_value()) { light_output_1->set_internal(false or relay_mode_index.value() != 1); @@ -457,48 +562,9 @@ script: light_output_4->set_internal(id(gang_count) < 4 or relay_mode_index.value() != 1); sw_relay_4->set_internal(id(gang_count) < 4 or relay_mode_index.value() != 0); } - const bool set_internal = not sw_expose_relays_leds_to_ha->state; - light_eu_rl_1_1_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); - light_eu_rl_1_1_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 1); - light_eu_rl_1_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); - light_eu_rl_1_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); - light_eu_rl_2_2_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); - light_eu_rl_2_2_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 2); - light_eu_rl_1_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_1_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_2_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_2_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_3_3_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_3_3_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 3); - light_eu_rl_1_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_1_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_2_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_2_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_3_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_3_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_4_4_bottom->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_eu_rl_4_4_top->set_internal(set_internal or id(is_us_model) or id(gang_count) != 4); - light_us_rl_1_1_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); - light_us_rl_1_1_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 1); - light_us_rl_1_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); - light_us_rl_1_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); - light_us_rl_2_2_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); - light_us_rl_2_2_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 2); - light_us_rl_1_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_1_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_2_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_2_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_3_3_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_3_3_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 3); - light_us_rl_1_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_1_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_2_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_2_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_3_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_3_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_4_4_left->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - light_us_rl_4_4_right->set_internal(set_internal or !id(is_us_model) or id(gang_count) != 4); - id(boot_initialization_relays) = true; + + // Set this section of initialization as completed + id(boot_initialization_relays_relay_modes) = true; - id: !extend button_click_event then: From cca59bbe2a322fd6034454c3e9a8d73de00fc553 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 25 Dec 2024 00:45:08 +0000 Subject: [PATCH 018/109] Bump version to 2024.12.18 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 569d179..df97f77 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.17 +2024.12.18 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index af59191..4e7b09f 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.17 +version: 2024.12.18 From e546fedf08386bc3a7c41fe10163a19eb3b13c6f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Dec 2024 02:11:10 +0100 Subject: [PATCH 019/109] Add dump config To help troubleshooting --- ...Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 6 ++ ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 56 +++++++++++++++++-- ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 14 +++++ ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 45 +++++++++++++-- ...te-Easy-ESPHome_core_hw_media_player.yaml} | 0 ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 34 +++++++++++ ...X-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 9 +++ ...timate-Easy-ESPHome_core_hw_vibration.yaml | 13 ++++- 8 files changed, 164 insertions(+), 13 deletions(-) rename ESPHome/{TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml => TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml} (100%) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index a18515c..743450c 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -96,6 +96,12 @@ rtttl: - id: rtttl_speaker speaker: mp_speaker +script: + - id: !extend dump_config + then: + - lambda: |- + ESP_LOGCONFIG("addon_ble_proxy", "Add-on BLE Proxy installed"); + speaker: - id: mp_speaker platform: i2s_audio diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index a05fdb3..82707d4 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -25,14 +25,16 @@ substitutions: TX_MODEL_3_GANG_TEXT: "3 Gang" TX_MODEL_4_GANG_TEXT: "4 Gang" + DUMP_CONFIG_CALLER_DELAY: 10s # Delay to dump config after requested + packages: # yamllint disable rule:colons - core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml - core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml - core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml - core_hw_speaker: !include TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml - core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml - core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml + core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml + core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml + core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml + core_hw_media_player: !include TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml + core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml + core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml # yamllint enable rule:colons api: @@ -40,6 +42,7 @@ api: on_client_connected: then: - script.execute: publish_device_info + - script.execute: dump_config_caller binary_sensor: - id: bs_pending_restart @@ -49,6 +52,13 @@ binary_sensor: platform: template entity_category: diagnostic device_class: problem + on_state: + then: + - lambda: |- + if (x) + ESP_LOGW("core", "Pending restart: YES"); + else + ESP_LOGCONFIG("core", "Pending restart: No"); button: - id: bt_restart @@ -158,6 +168,40 @@ script: id: bs_pending_restart state: false + - id: dump_config + mode: restart + then: + # Extended by all modules + - lambda: |- + ESP_LOGCONFIG("core", "Device friendly name: ${friendly_name}"); + ESP_LOGCONFIG("core", "Device name: ${name}"); + ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str()); + ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str()); + ESP_LOGCONFIG("core", "ESPHome builder: %s", esphome_fw_version->state.c_str()); + ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); + // Report framework + #ifdef ARDUINO + ESP_LOGCONFIG("core", "Framework: Arduino"); + #elif defined(USE_ESP_IDF) + ESP_LOGCONFIG("core", "Framework: ESP-IDF"); + #else + ESP_LOGW("core", "Framework: UNKNOWN"); + #endif + ESP_LOGCONFIG("core", "Model format (selected): %s", sl_tx_model_format->state.c_str()); + ESP_LOGCONFIG("core", "Model format (detected): %s", id(is_us_model) ? "US" : "EU"); + ESP_LOGCONFIG("core", "Gangs (selected): %s", sl_tx_model_gang->state.c_str()); + ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count) == 1 ? "" : "s"); + if (bs_pending_restart->state) + ESP_LOGW("core", "Pending restart: YES"); + else + ESP_LOGCONFIG("core", "Pending restart: No"); + + - id: dump_config_caller + mode: restart + then: + - delay: ${DUMP_CONFIG_CALLER_DELAY} + - script.execute: dump_config + - id: publish_device_info mode: restart then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index de16ddc..4c15f70 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -200,6 +200,20 @@ script: } } + - id: !extend dump_config + then: + - lambda: |- + ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:", + id(gang_count) == 1 ? "" : "s", + id(gang_count) == 1 ? "" : "s"); + ESP_LOGCONFIG("core_hw_buttons", " Relay 1: %s", sl_button_1_action->state.c_str()); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("core_hw_buttons", " Relay 2: %s", sl_button_2_action->state.c_str()); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("core_hw_buttons", " Relay 3: %s", sl_button_3_action->state.c_str()); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("core_hw_buttons", " Relay 4: %s", sl_button_4_action->state.c_str()); + - id: !extend touch_on_multi_touch_release then: - script.execute: buttons_release diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index b71944c..bb2ae57 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -481,8 +481,47 @@ script: light_eu_rl_3_4_top, light_eu_rl_4_4_top }; } break; + default: + ESP_LOGE("core_hw_leds", "Invalid gang count: %" PRIu8, id(gang_count)); + break; } + - id: !extend dump_config + then: + - lambda: |- + ESP_LOGCONFIG("core_hw_leds", "Relay%s LEDs mode%s:", + id(gang_count) == 1 ? "" : "s", + id(gang_count) == 1 ? "" : "s"); + ESP_LOGCONFIG("core_hw_leds", " Relay 1: %s", id(is_us_model) + ? sl_relay_1_light_mode_us->state.c_str() + : sl_relay_1_light_mode_eu->state.c_str()); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("core_hw_leds", " Relay 2: %s", id(is_us_model) + ? sl_relay_2_light_mode_us->state.c_str() + : sl_relay_2_light_mode_eu->state.c_str()); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("core_hw_leds", " Relay 3: %s", id(is_us_model) + ? sl_relay_3_light_mode_us->state.c_str() + : sl_relay_3_light_mode_eu->state.c_str()); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("core_hw_leds", " Relay 4: %s", id(is_us_model) + ? sl_relay_4_light_mode_us->state.c_str() + : sl_relay_4_light_mode_eu->state.c_str()); + ESP_LOGCONFIG("core_hw_leds", "Transition time:"); + ESP_LOGCONFIG("core_hw_leds", " Default: ${default_transition_length}"); + if (${LIGHT_TRANSITION_TURN_ON} > 0) + ESP_LOGCONFIG("core_hw_leds", " Turning on: ${LIGHT_TRANSITION_TURN_ON}ms"); + else + ESP_LOGCONFIG("core_hw_leds", " Turning on: Disabled"); + if (${LIGHT_TRANSITION_TURN_OFF} > 0) + ESP_LOGCONFIG("core_hw_leds", " Turning off: ${LIGHT_TRANSITION_TURN_OFF}ms"); + else + ESP_LOGCONFIG("core_hw_leds", " Turning off: Disabled"); + ESP_LOGCONFIG("core_hw_leds", "LED restore modes:"); + ESP_LOGCONFIG("core_hw_leds", " Light - All: ${LIGHT_FULL_RESTORE_MODE}"); + ESP_LOGCONFIG("core_hw_leds", " Sides: ${LIGHT_SIDES_RESTORE_MODE}"); + ESP_LOGCONFIG("core_hw_leds", " Individual: ${LIGHT_INDIVIDUAL_RESTORE_MODE}"); + - id: light_set_state mode: parallel parameters: @@ -571,15 +610,12 @@ select: entity_category: config disabled_by_default: false icon: mdi:dots-square - - id: sl_relay_2_light_mode_eu name: Relay 2 light mode <<: *relay_light_mode_eu - - id: sl_relay_3_light_mode_eu name: Relay 3 light mode <<: *relay_light_mode_eu - - id: sl_relay_4_light_mode_eu name: Relay 4 light mode <<: *relay_light_mode_eu @@ -601,15 +637,12 @@ select: entity_category: config disabled_by_default: false icon: mdi:dots-square - - id: sl_relay_2_light_mode_us name: Relay 2 light mode <<: *relay_light_mode_us - - id: sl_relay_3_light_mode_us name: Relay 3 light mode <<: *relay_light_mode_us - - id: sl_relay_4_light_mode_us name: Relay 4 light mode <<: *relay_light_mode_us diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml similarity index 100% rename from ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_speaker.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index 5f47897..1aa82bb 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -634,6 +634,40 @@ script: ESP_LOGE("core_hw_relays", "No button action selected for button %" PRIu8, button); } + - id: !extend dump_config + then: + - lambda: |- + ESP_LOGCONFIG("core_hw_relays", "Relay%s mode%s:", + id(gang_count) == 1 ? "" : "s", + id(gang_count) == 1 ? "" : "s"); + ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sl_relay_1_mode->state.c_str()); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sl_relay_2_mode->state.c_str()); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sl_relay_3_mode->state.c_str()); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->state.c_str()); + ESP_LOGCONFIG("core_hw_relays", "Relay%s state%s:", + id(gang_count) == 1 ? "" : "s", + id(gang_count) == 1 ? "" : "s"); + ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sw_relay_1->state ? "ON" : "OFF"); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sw_relay_2->state ? "ON" : "OFF"); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sw_relay_3->state ? "ON" : "OFF"); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sw_relay_4->state ? "ON" : "OFF"); + ESP_LOGCONFIG("core_hw_relays", "Expose Relay's LEDs to Home Assistant: %s", + YESNO(sw_expose_relays_leds_to_ha->state)); + ESP_LOGCONFIG("core_hw_relays", "Boot initialization flags:"); + ESP_LOGCONFIG("core_hw_relays", " Overall: %s", YESNO(id(boot_initialization_relays))); + ESP_LOGCONFIG("core_hw_relays", " Light modes: %s", YESNO(id(boot_initialization_relays_light_modes))); + ESP_LOGCONFIG("core_hw_relays", " Relay modes: %s", YESNO(id(boot_initialization_relays_relay_modes))); + ESP_LOGCONFIG("core_hw_relays", " Status LEDs: %s", YESNO(id(boot_initialization_relays_relay_leds))); + ESP_LOGCONFIG("core_hw_relays", "Restore modes:"); + ESP_LOGCONFIG("core_hw_relays", " Relays: ${RELAY_RESTORE_MODE}"); + ESP_LOGCONFIG("core_hw_relays", " Status LEDs: ${LIGHT_RELAYS_RESTORE_MODE}"); + - id: show_relay_status mode: restart then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index 1d204c9..f840b9d 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -283,6 +283,15 @@ script: bs_button_3_long_press_event->set_internal(id(gang_count) < 3); bs_button_4_long_press_event->set_internal(id(gang_count) < 4); + - id: !extend dump_config + then: + - lambda: |- + if (sw_touch_panel_power->state) + ESP_LOGCONFIG("core_hw_touch", "Touch panel - Power: On"); + else + ESP_LOGW("core_hw_touch", "Touch panel - Power: OFF"); + ESP_LOGCONFIG("core_hw_touch", "Touch event duration: %.0fms", nr_touch_duration->state); + - id: touch_on_multi_touch_release mode: restart then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml index 67655c1..09c8fc7 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml @@ -53,6 +53,18 @@ ota: - switch.turn_off: sw_vibration_motor script: + - id: !extend dump_config + then: + - lambda: |- + ESP_LOGCONFIG("core_hw_vibration", "Touch - Vibration feedback: %s", + sl_touch_vibration_feedback->state.c_str()); + ESP_LOGCONFIG("core_hw_vibration", "Vibrate duration: %.0fms", nr_vibrating_duration->state); + ESP_LOGCONFIG("core_hw_vibration", "Vibrate max duration: ${vibration_max_duration}"); + if (bs_vibrating->state) + ESP_LOGW("core_hw_vibration", "Vibrating now: YES"); + else + ESP_LOGCONFIG("core_hw_vibration", "Vibrating now: No"); + - id: !extend touch_on_multi_touch_release then: - script.execute: touch_on_multi_touch_release_vibration @@ -133,5 +145,4 @@ switch: - binary_sensor.template.publish: id: bs_vibrating state: OFF # yamllint disable-line rule:truthy - ... From 7aee88c38f7d91c2506d25eae66a3e619939ea65 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Dec 2024 02:34:18 +0100 Subject: [PATCH 020/109] CodeRabbitAI suggestions --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 24 +++++++++++++++---- ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 4 ++-- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 11 ++++++--- ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 8 +++---- ...timate-Easy-ESPHome_core_hw_vibration.yaml | 3 +++ 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 82707d4..32d9c55 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -31,8 +31,8 @@ packages: # yamllint disable rule:colons core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml - core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml core_hw_media_player: !include TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml + core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml # yamllint enable rule:colons @@ -41,8 +41,8 @@ api: id: api_server on_client_connected: then: - - script.execute: publish_device_info - script.execute: dump_config_caller + - script.execute: publish_device_info binary_sensor: - id: bs_pending_restart @@ -59,6 +59,7 @@ binary_sensor: ESP_LOGW("core", "Pending restart: YES"); else ESP_LOGCONFIG("core", "Pending restart: No"); + - script.execute: dump_config_caller button: - id: bt_restart @@ -105,6 +106,12 @@ globals: restore_value: true initial_value: '0' + - id: gang_count_plural_suffix + type: std::string + restore_value: true + max_restore_data_length: 3 + # initial_value: "''" + improv_serial: id: serial_improv @@ -159,6 +166,7 @@ script: if (id(gang_count) < 1 || id(gang_count) > 4) { ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, id(gang_count)); } + id(gang_count_plural_suffix) = id(gang_count) > 1 ? "s" : ""; - id: boot_sequence mode: restart @@ -173,13 +181,17 @@ script: then: # Extended by all modules - lambda: |- + // Device identification ESP_LOGCONFIG("core", "Device friendly name: ${friendly_name}"); ESP_LOGCONFIG("core", "Device name: ${name}"); ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str()); ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str()); + + // Version information ESP_LOGCONFIG("core", "ESPHome builder: %s", esphome_fw_version->state.c_str()); ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); - // Report framework + + // Framework detection #ifdef ARDUINO ESP_LOGCONFIG("core", "Framework: Arduino"); #elif defined(USE_ESP_IDF) @@ -187,10 +199,14 @@ script: #else ESP_LOGW("core", "Framework: UNKNOWN"); #endif + + // Model configuration ESP_LOGCONFIG("core", "Model format (selected): %s", sl_tx_model_format->state.c_str()); ESP_LOGCONFIG("core", "Model format (detected): %s", id(is_us_model) ? "US" : "EU"); ESP_LOGCONFIG("core", "Gangs (selected): %s", sl_tx_model_gang->state.c_str()); - ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count) == 1 ? "" : "s"); + ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count_plural_suffix).c_str()); + + // System state if (bs_pending_restart->state) ESP_LOGW("core", "Pending restart: YES"); else diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index 4c15f70..7cb3039 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -204,8 +204,8 @@ script: then: - lambda: |- ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:", - id(gang_count) == 1 ? "" : "s", - id(gang_count) == 1 ? "" : "s"); + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); ESP_LOGCONFIG("core_hw_buttons", " Relay 1: %s", sl_button_1_action->state.c_str()); if (id(gang_count) >= 2) ESP_LOGCONFIG("core_hw_buttons", " Relay 2: %s", sl_button_2_action->state.c_str()); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index bb2ae57..087ce46 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -489,9 +489,10 @@ script: - id: !extend dump_config then: - lambda: |- + // Relay's LEDs modes ESP_LOGCONFIG("core_hw_leds", "Relay%s LEDs mode%s:", - id(gang_count) == 1 ? "" : "s", - id(gang_count) == 1 ? "" : "s"); + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); ESP_LOGCONFIG("core_hw_leds", " Relay 1: %s", id(is_us_model) ? sl_relay_1_light_mode_us->state.c_str() : sl_relay_1_light_mode_eu->state.c_str()); @@ -507,7 +508,9 @@ script: ESP_LOGCONFIG("core_hw_leds", " Relay 4: %s", id(is_us_model) ? sl_relay_4_light_mode_us->state.c_str() : sl_relay_4_light_mode_eu->state.c_str()); - ESP_LOGCONFIG("core_hw_leds", "Transition time:"); + + // Transition times + ESP_LOGCONFIG("core_hw_leds", "Transition times:"); ESP_LOGCONFIG("core_hw_leds", " Default: ${default_transition_length}"); if (${LIGHT_TRANSITION_TURN_ON} > 0) ESP_LOGCONFIG("core_hw_leds", " Turning on: ${LIGHT_TRANSITION_TURN_ON}ms"); @@ -517,6 +520,8 @@ script: ESP_LOGCONFIG("core_hw_leds", " Turning off: ${LIGHT_TRANSITION_TURN_OFF}ms"); else ESP_LOGCONFIG("core_hw_leds", " Turning off: Disabled"); + + // Restore modes ESP_LOGCONFIG("core_hw_leds", "LED restore modes:"); ESP_LOGCONFIG("core_hw_leds", " Light - All: ${LIGHT_FULL_RESTORE_MODE}"); ESP_LOGCONFIG("core_hw_leds", " Sides: ${LIGHT_SIDES_RESTORE_MODE}"); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index 1aa82bb..f58e374 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -638,8 +638,8 @@ script: then: - lambda: |- ESP_LOGCONFIG("core_hw_relays", "Relay%s mode%s:", - id(gang_count) == 1 ? "" : "s", - id(gang_count) == 1 ? "" : "s"); + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sl_relay_1_mode->state.c_str()); if (id(gang_count) >= 2) ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sl_relay_2_mode->state.c_str()); @@ -648,8 +648,8 @@ script: if (id(gang_count) >= 4) ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->state.c_str()); ESP_LOGCONFIG("core_hw_relays", "Relay%s state%s:", - id(gang_count) == 1 ? "" : "s", - id(gang_count) == 1 ? "" : "s"); + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sw_relay_1->state ? "ON" : "OFF"); if (id(gang_count) >= 2) ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sw_relay_2->state ? "ON" : "OFF"); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml index 09c8fc7..fd19fb9 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml @@ -56,10 +56,13 @@ script: - id: !extend dump_config then: - lambda: |- + // Configuration ESP_LOGCONFIG("core_hw_vibration", "Touch - Vibration feedback: %s", sl_touch_vibration_feedback->state.c_str()); ESP_LOGCONFIG("core_hw_vibration", "Vibrate duration: %.0fms", nr_vibrating_duration->state); ESP_LOGCONFIG("core_hw_vibration", "Vibrate max duration: ${vibration_max_duration}"); + + // State if (bs_vibrating->state) ESP_LOGW("core_hw_vibration", "Vibrating now: YES"); else From 5ddf5388bd41d1efa3c39f02ab5c43350b114408 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Dec 2024 03:00:56 +0100 Subject: [PATCH 021/109] Handle unknown states --- ...TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 16 ++++++++++++---- .../TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index 7cb3039..43c8717 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -206,13 +206,21 @@ script: ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); - ESP_LOGCONFIG("core_hw_buttons", " Relay 1: %s", sl_button_1_action->state.c_str()); + ESP_LOGCONFIG("core_hw_buttons", " Relay 1: %s", sl_button_1_action->has_state() + ? sl_button_1_action->state.c_str() + : "Unknown"); if (id(gang_count) >= 2) - ESP_LOGCONFIG("core_hw_buttons", " Relay 2: %s", sl_button_2_action->state.c_str()); + ESP_LOGCONFIG("core_hw_buttons", " Relay 2: %s", sl_button_2_action->has_state() + ? sl_button_2_action->state.c_str() + : "Unknown"); if (id(gang_count) >= 3) - ESP_LOGCONFIG("core_hw_buttons", " Relay 3: %s", sl_button_3_action->state.c_str()); + ESP_LOGCONFIG("core_hw_buttons", " Relay 3: %s", sl_button_3_action->has_state() + ? sl_button_3_action->state.c_str() + : "Unknown"); if (id(gang_count) >= 4) - ESP_LOGCONFIG("core_hw_buttons", " Relay 4: %s", sl_button_4_action->state.c_str()); + ESP_LOGCONFIG("core_hw_buttons", " Relay 4: %s", sl_button_4_action->has_state() + ? sl_button_4_action->state.c_str() + : "Unknown"); - id: !extend touch_on_multi_touch_release then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index f58e374..ee1c16e 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -640,13 +640,21 @@ script: ESP_LOGCONFIG("core_hw_relays", "Relay%s mode%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); - ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sl_relay_1_mode->state.c_str()); + ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sl_relay_1_mode->has_state() + ? sl_relay_1_mode->state.c_str() + : "Unknown"); if (id(gang_count) >= 2) - ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sl_relay_2_mode->state.c_str()); + ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sl_relay_2_mode->has_state() + ? sl_relay_2_mode->state.c_str() + : "Unknown"); if (id(gang_count) >= 3) - ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sl_relay_3_mode->state.c_str()); + ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sl_relay_3_mode->has_state() + ? sl_relay_3_mode->state.c_str() + : "Unknown"); if (id(gang_count) >= 4) - ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->state.c_str()); + ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->has_state() + ? sl_relay_4_mode->state.c_str() + : "Unknown"); ESP_LOGCONFIG("core_hw_relays", "Relay%s state%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); From 4378952d979662138dcb8f8844a5d69a471fbf76 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Wed, 25 Dec 2024 02:06:44 +0000 Subject: [PATCH 022/109] Bump version to 2024.12.19 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index df97f77..035e90a 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.18 +2024.12.19 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 4e7b09f..5803b9d 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.18 +version: 2024.12.19 From 81c6620fbf6b958e6b7fc2b7c5073585f575cfb2 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Dec 2024 23:01:33 +0100 Subject: [PATCH 023/109] Split files even more --- ...Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 93 +-------- ...imate-Easy-ESPHome_addon_media_player.yaml | 51 +++++ ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 176 ++++++++++++++++++ ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 17 +- ...X-Ultimate-Easy-ESPHome_core_hw_audio.yaml | 32 ++++ ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 11 ++ ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 20 +- ...-Ultimate-Easy-ESPHome_core_hw_relays.yaml | 16 ++ ...X-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 11 ++ ...timate-Easy-ESPHome_core_hw_vibration.yaml | 10 + README.md | 1 + TX-Ultimate-Easy-ESPHome.yaml | 4 +- 12 files changed, 348 insertions(+), 94 deletions(-) create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 743450c..9f644a8 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -11,103 +11,22 @@ ##### - For normal system use, modifications to this file are NOT required. ##### #################################################################################################### --- -substitutions: - # RTTTL format: name:d=duration,o=octave,b=tempo:notes - # d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100) - tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound - -api: - actions: - - action: rtttl_play - variables: - # The RTTTL string for the melody to be played. - # It should follow the RTTTL format, including the melody's name, - # default settings, and a sequence of notes. - tone: string - then: - - lambda: |- - rtttl_speaker->stop(); - if (rtttl_speaker_gain->state > 0) { - ESP_LOGI("api", "Play tone: '%s'", tone.c_str()); - rtttl_speaker->play(tone.c_str()); - } - bluetooth_proxy: -esp32: - framework: - type: esp-idf - sdkconfig_options: - CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" - CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" - CONFIG_ESP32_REV_MIN_3: "y" - CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" - CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" - CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" - CONFIG_SPIRAM_RODATA: "y" - CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" - esphome: platformio_options: build_flags: - -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY -light: - - id: !extend light_full - platform: esp32_rmt_led_strip - rgb_order: GRB - rmt_channel: 1 - chipset: ws2812 - type: !remove - variant: !remove - max_refresh_rate: 33ms - use_psram: true - -media_player: !remove - -number: - - id: rtttl_speaker_gain - name: Sound - Volume - platform: template - max_value: 100 - min_value: 0 - step: 1 - initial_value: 100 - unit_of_measurement: "%" - internal: false - disabled_by_default: true - entity_category: config - device_class: sound_pressure - restore_value: true - optimistic: true - set_action: - then: - - lambda: |- - rtttl_speaker->set_gain((100-(x/10.0f))/100.0f); - std::string tone_volume_change = "${tone_volume_change}"; - // Play sound if tone_volume_change is not "none" - if (x > 0 and !tone_volume_change.empty() and tone_volume_change != "none") - rtttl_speaker->play(tone_volume_change); - rtttl_speaker->dump_config(); - -rtttl: - - id: rtttl_speaker - speaker: mp_speaker - script: - id: !extend dump_config then: - lambda: |- - ESP_LOGCONFIG("addon_ble_proxy", "Add-on BLE Proxy installed"); + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif -speaker: - - id: mp_speaker - platform: i2s_audio - dac_type: external - i2s_dout_pin: GPIO15 - i2s_audio_id: if_i2s_audio - i2s_comm_fmt: stand_msb - channel: mono + // Identify itself + ESP_LOGCONFIG("addon_ble_proxy", "Add-on BLE Proxy installed"); ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml new file mode 100644 index 0000000..32f9b74 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml @@ -0,0 +1,51 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome - Add-on - Media player ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +packages: + core_hw_audio: !include TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml + +esp32: + framework: + type: arduino + +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_ADDON_MEDIA_PLAYER + +media_player: + - id: mp_media_player + name: Media Player + internal: false + platform: i2s_audio + i2s_dout_pin: GPIO15 + i2s_audio_id: if_i2s_audio + i2s_comm_fmt: msb # Experimental - It was 'lsb' until v2024.12.12 + dac_type: external + mode: mono + +script: + - id: !extend dump_config + then: + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + #if !defined(TX_ULTIMATE_EASY_CORE_HW_AUDIO) + #error "The package TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG("addon_media_player", "Add-on Media Player installed"); +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml new file mode 100644 index 0000000..169e62c --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -0,0 +1,176 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome - Add-on - Speaker ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +substitutions: + # RTTTL format: name:d=duration,o=octave,b=tempo:notes + # d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100) + tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound + + click_sound: |- + [ + 0x01,0x02,0x04,0x06,0x07,0x08,0x08,0x06,0x01,0xFA,0xF4,0xEF,0xEE,0xF1,0xF7,0xFF,0x07,0x0E, + 0x11,0x11,0x10,0x0C,0x06,0xFF,0xF8,0xF1,0xEC,0xEA,0xEC,0xF2,0xF9,0xFF,0x05,0x0A,0x10,0x14, + 0x17,0x17,0x14,0x0B,0xFD,0xED,0xE0,0xD9,0xDB,0xE6,0xF7,0x0A,0x19,0x20,0x1E,0x14,0x05,0xF4, + 0xE5,0xDF,0xE4,0xF4,0x0C,0x24,0x36,0x3D,0x35,0x20,0xFF,0xDD,0xC0,0xAE,0xA9,0xB0,0xC4,0xE0, + 0x03,0x26,0x48,0x62,0x70,0x6D,0x59,0x35,0x08,0xD8,0xAC,0x8D,0x80,0x85,0x9C,0xC1,0xF0,0x21, + 0x4E,0x6F,0x7F,0x7A,0x63,0x3D,0x0F,0xE0,0xB7,0x9B,0x90,0x96,0xAC,0xCE,0xF6,0x1D,0x3C,0x50, + 0x55,0x4D,0x3A,0x20,0x04,0xEC,0xD8,0xCC,0xC9,0xCD,0xD8,0xE8,0xF9,0x0A,0x17,0x1F,0x20,0x1C, + 0x12,0x07,0xFC,0xF2,0xEC,0xEB,0xED,0xF3,0xFA,0x02,0x0A,0x10,0x12,0x12,0x0E,0x07,0xFE,0xF5, + 0xED,0xEA,0xEB,0xEF,0xF7,0x00,0x0A,0x10,0x13,0x12,0x0F,0x09,0x02,0xFB,0xF5,0xF3,0xF2,0xF3, + 0xF6,0xFB,0xFF,0x03,0x05,0x07,0x08,0x07,0x05,0x03,0x01,0xFF,0xFE,0xFC,0xFB,0xFB,0xFC,0xFC, + 0xFD,0xFE,0xFF,0x00,0x01,0x02,0x02,0x01 + ] + +packages: + core_hw_audio: !include TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml + +api: + actions: + - action: rtttl_play + variables: + # The RTTTL string for the melody to be played. + # It should follow the RTTTL format, including the melody's name, + # default settings, and a sequence of notes. + tone: string + then: + - lambda: |- + rtttl_speaker->stop(); + if (rtttl_speaker_gain->state > 0) { + ESP_LOGI("api", "Play tone: '%s'", tone.c_str()); + rtttl_speaker->play(tone.c_str()); + } + +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_ADDON_SPEAKER + +number: + - id: rtttl_speaker_gain + name: Sound - Volume + platform: template + max_value: 100 + min_value: 0 + step: 1 + initial_value: 100 + unit_of_measurement: "%" + internal: false + disabled_by_default: true + entity_category: config + device_class: sound_pressure + restore_value: true + optimistic: true + set_action: + then: + - lambda: |- + rtttl_speaker->set_gain((100-(x/10.0f))/100.0f); + std::string tone_volume_change = "${tone_volume_change}"; + // Play sound if tone_volume_change is not "none" + if (x > 0 and !tone_volume_change.empty() and tone_volume_change != "none") + rtttl_speaker->play(tone_volume_change); + rtttl_speaker->dump_config(); + +rtttl: + - id: rtttl_speaker + speaker: speaker_embedded + +script: + - id: !extend dump_config + then: + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + #if !defined(TX_ULTIMATE_EASY_CORE_HW_AUDIO) + #error "The package TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG("addon_speaker", "Add-on Speaker installed"); + + - id: speaker_play_click + then: + - if: + condition: + not: + - speaker.is_playing: speaker_embedded + then: + - speaker.play: + id: speaker_embedded + data: !lambda return std::vector(${click_sound}); + - wait_until: + condition: + not: + - speaker.is_playing: speaker_embedded + - speaker.stop: speaker_embedded + + - id: !extend touch_on_multi_touch_release + then: + - script.execute: touch_on_multi_touch_release_speaker + + - id: touch_on_multi_touch_release_speaker + mode: restart + then: + - lambda: |- + if (sl_touch_speaker_feedback->state != "Disabled") + vibrate->execute(); + + - id: !extend touch_on_press + then: + - script.execute: touch_on_press_speaker + + - id: touch_on_press_speaker + mode: restart + then: + - lambda: |- + if (sl_touch_speaker_feedback->state == "On press" or sl_touch_speaker_feedback->state == "Always") + vibrate->execute(); + + - id: !extend touch_on_release + then: + - script.execute: touch_on_release_speaker + + - id: touch_on_release_speaker + mode: restart + then: + - lambda: |- + if (sl_touch_speaker_feedback->state == "On release" or sl_touch_speaker_feedback->state == "Always") + vibrate->execute(); + +select: + - id: sl_touch_speaker_feedback + name: Touch - Speaker feedback + platform: template + options: + - "Disabled" + - "On press" + - "On release" + - "Always" + initial_option: "Disabled" + optimistic: true + restore_value: true + internal: false + entity_category: config + disabled_by_default: false + icon: mdi:vibrate + +speaker: + - id: speaker_embedded + platform: i2s_audio + dac_type: external + i2s_dout_pin: GPIO15 + i2s_audio_id: if_i2s_audio + i2s_comm_fmt: stand_msb + channel: mono +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 32d9c55..c6e78fd 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -31,7 +31,6 @@ packages: # yamllint disable rule:colons core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml - core_hw_media_player: !include TX-Ultimate-Easy-ESPHome_core_hw_media_player.yaml core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml @@ -71,8 +70,22 @@ captive_portal: id: ap_captive_portal esp32: - board: esp32dev + board: esp32dev # adafruit_feather_esp32_v2 # esp32dev flash_size: 8MB + framework: + type: esp-idf + #sdkconfig_options: + #CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" + #CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" + #CONFIG_ESP32_REV_MIN_3: "y" + #CONFIG_ESPTOOLPY_FLASHSIZE_8MB: "y" + #CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" + #CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" + #CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" + #CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" + #CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" + #CONFIG_SPIRAM_RODATA: "y" + #CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" esphome: name: ${name} diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml new file mode 100644 index 0000000..c9a91e2 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml @@ -0,0 +1,32 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome - Core - I2S Audio ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_AUDIO + +i2s_audio: + id: if_i2s_audio + i2s_bclk_pin: GPIO2 + i2s_lrclk_pin: GPIO4 + +script: + - id: !extend dump_config + then: + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index 43c8717..446e344 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -57,6 +57,11 @@ binary_sensor: internal: false <<: *binary_sensor_button_base +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_BUTTONS + globals: - id: button_press_button type: uint8_t @@ -203,6 +208,12 @@ script: - id: !extend dump_config then: - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Button's actions ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 087ce46..219e354 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -29,6 +29,11 @@ substitutions: LIGHT_SIDES_RESTORE_MODE: RESTORE_DEFAULT_OFF LIGHT_INDIVIDUAL_RESTORE_MODE: RESTORE_DEFAULT_OFF +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_LEDS + globals: - id: gb_lights_1 type: std::vector @@ -42,13 +47,15 @@ light: - id: light_full name: Light - All internal: true - platform: neopixelbus - type: GRB - variant: WS2811 - # method: esp32_rmt + platform: esp32_rmt_led_strip + rgb_order: GRB + rmt_channel: 1 + chipset: ws2812 num_leds: 32 pin: GPIO13 restore_mode: ${LIGHT_FULL_RESTORE_MODE} + max_refresh_rate: 33ms + use_psram: true # Those lights are available based on the model selections - &light_partition_with_effects @@ -489,6 +496,11 @@ script: - id: !extend dump_config then: - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + // Relay's LEDs modes ESP_LOGCONFIG("core_hw_leds", "Relay%s LEDs mode%s:", id(gang_count_plural_suffix).c_str(), diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml index ee1c16e..7fa0809 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml @@ -19,6 +19,10 @@ substitutions: RELAY_RESTORE_MODE: RESTORE_DEFAULT_OFF LIGHT_RELAYS_RESTORE_MODE: RESTORE_DEFAULT_OFF +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_RELAYS globals: - id: boot_initialization_relays @@ -637,6 +641,12 @@ script: - id: !extend dump_config then: - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Relay's modes ESP_LOGCONFIG("core_hw_relays", "Relay%s mode%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); @@ -655,6 +665,8 @@ script: ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->has_state() ? sl_relay_4_mode->state.c_str() : "Unknown"); + + // Relay's states ESP_LOGCONFIG("core_hw_relays", "Relay%s state%s:", id(gang_count_plural_suffix).c_str(), id(gang_count_plural_suffix).c_str()); @@ -667,11 +679,15 @@ script: ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sw_relay_4->state ? "ON" : "OFF"); ESP_LOGCONFIG("core_hw_relays", "Expose Relay's LEDs to Home Assistant: %s", YESNO(sw_expose_relays_leds_to_ha->state)); + + // Boot initialization statuses ESP_LOGCONFIG("core_hw_relays", "Boot initialization flags:"); ESP_LOGCONFIG("core_hw_relays", " Overall: %s", YESNO(id(boot_initialization_relays))); ESP_LOGCONFIG("core_hw_relays", " Light modes: %s", YESNO(id(boot_initialization_relays_light_modes))); ESP_LOGCONFIG("core_hw_relays", " Relay modes: %s", YESNO(id(boot_initialization_relays_relay_modes))); ESP_LOGCONFIG("core_hw_relays", " Status LEDs: %s", YESNO(id(boot_initialization_relays_relay_leds))); + + // Substitutions ESP_LOGCONFIG("core_hw_relays", "Restore modes:"); ESP_LOGCONFIG("core_hw_relays", " Relays: ${RELAY_RESTORE_MODE}"); ESP_LOGCONFIG("core_hw_relays", " Status LEDs: ${LIGHT_RELAYS_RESTORE_MODE}"); diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index f840b9d..f5c0157 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -198,6 +198,11 @@ binary_sensor: id: bs_swipe_down state: OFF # yamllint disable-line rule:truthy +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_TOUCH + external_components: - source: type: git @@ -286,6 +291,12 @@ script: - id: !extend dump_config then: - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Touch panel's state if (sw_touch_panel_power->state) ESP_LOGCONFIG("core_hw_touch", "Touch panel - Power: On"); else diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml index fd19fb9..4587626 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml @@ -32,6 +32,11 @@ button: then: - script.execute: vibrate +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE_HW_VIBRATION + number: - id: nr_vibrating_duration name: Vibrate duration @@ -56,6 +61,11 @@ script: - id: !extend dump_config then: - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + // Configuration ESP_LOGCONFIG("core_hw_vibration", "Touch - Vibration feedback: %s", sl_touch_vibration_feedback->state.c_str()); diff --git a/README.md b/README.md index 4918684..b6b6b29 100644 --- a/README.md +++ b/README.md @@ -156,6 +156,7 @@ This project builds upon the work of several amazing projects and contributors: - [SmartHome yourself - SONOFF TX Ultimate for ESPHome](https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome) - [Un loco y su tecnología - Sonoff TX Ultimate with ESPHome](https://www.youtube.com/watch?v=58v8oqSQgXQ) +- @PxPert - [Sonoff TX Ultimate and Voice Assistant](https://community.home-assistant.io/t/sonoff-tx-ultimate-and-voice-assistant/682214?u=edwardtfn) Special thanks to all contributors and community members who help make this project better. diff --git a/TX-Ultimate-Easy-ESPHome.yaml b/TX-Ultimate-Easy-ESPHome.yaml index 9823def..4e1c17d 100644 --- a/TX-Ultimate-Easy-ESPHome.yaml +++ b/TX-Ultimate-Easy-ESPHome.yaml @@ -20,5 +20,7 @@ packages: refresh: 5min files: - ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds experimental BLE proxy support (limited) + # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support + # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml # Adds experimental Media Player (limited) + # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml # Adds basic audio speaker support ... From f3b84e9d4e0ff158917e29a70dc63e5e92458ffe Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 00:27:48 +0100 Subject: [PATCH 024/109] Fix calls to speaker_play_click --- ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 20 ++++++++----------- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 14 +------------ 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index 169e62c..9d58bac 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -45,7 +45,7 @@ api: then: - lambda: |- rtttl_speaker->stop(); - if (rtttl_speaker_gain->state > 0) { + if (speaker_volume->state > 0) { ESP_LOGI("api", "Play tone: '%s'", tone.c_str()); rtttl_speaker->play(tone.c_str()); } @@ -56,7 +56,7 @@ esphome: - -D TX_ULTIMATE_EASY_ADDON_SPEAKER number: - - id: rtttl_speaker_gain + - id: speaker_volume name: Sound - Volume platform: template max_value: 100 @@ -72,13 +72,9 @@ number: optimistic: true set_action: then: - - lambda: |- - rtttl_speaker->set_gain((100-(x/10.0f))/100.0f); - std::string tone_volume_change = "${tone_volume_change}"; - // Play sound if tone_volume_change is not "none" - if (x > 0 and !tone_volume_change.empty() and tone_volume_change != "none") - rtttl_speaker->play(tone_volume_change); - rtttl_speaker->dump_config(); + - speaker.volume_set: + id: speaker_embedded + volume: !lambda return x/100.0f; rtttl: - id: rtttl_speaker @@ -124,7 +120,7 @@ script: then: - lambda: |- if (sl_touch_speaker_feedback->state != "Disabled") - vibrate->execute(); + speaker_play_click->execute(); - id: !extend touch_on_press then: @@ -135,7 +131,7 @@ script: then: - lambda: |- if (sl_touch_speaker_feedback->state == "On press" or sl_touch_speaker_feedback->state == "Always") - vibrate->execute(); + speaker_play_click->execute(); - id: !extend touch_on_release then: @@ -146,7 +142,7 @@ script: then: - lambda: |- if (sl_touch_speaker_feedback->state == "On release" or sl_touch_speaker_feedback->state == "Always") - vibrate->execute(); + speaker_play_click->execute(); select: - id: sl_touch_speaker_feedback diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index c6e78fd..c5749a7 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -74,18 +74,6 @@ esp32: flash_size: 8MB framework: type: esp-idf - #sdkconfig_options: - #CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" - #CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" - #CONFIG_ESP32_REV_MIN_3: "y" - #CONFIG_ESPTOOLPY_FLASHSIZE_8MB: "y" - #CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" - #CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" - #CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" - #CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" - #CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" - #CONFIG_SPIRAM_RODATA: "y" - #CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" esphome: name: ${name} @@ -205,7 +193,7 @@ script: ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); // Framework detection - #ifdef ARDUINO + #ifdef USE_ARDUINO ESP_LOGCONFIG("core", "Framework: Arduino"); #elif defined(USE_ESP_IDF) ESP_LOGCONFIG("core", "Framework: ESP-IDF"); From c22d8eb847d70997e5867ab6ef388da358bd717a Mon Sep 17 00:00:00 2001 From: arnonh Date: Thu, 26 Dec 2024 21:13:22 +0200 Subject: [PATCH 025/109] Update tx_ultimate_easy.cpp Fix for 4 gang button position calculation reflects better the old positions --- components/tx_ultimate_easy/tx_ultimate_easy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/tx_ultimate_easy/tx_ultimate_easy.cpp b/components/tx_ultimate_easy/tx_ultimate_easy.cpp index 640f3db..2c023bd 100644 --- a/components/tx_ultimate_easy/tx_ultimate_easy.cpp +++ b/components/tx_ultimate_easy/tx_ultimate_easy.cpp @@ -68,9 +68,9 @@ namespace esphome { if (this->gang_count_ == 1) return 1; - // Calculate button number - const uint8_t width = (TOUCH_MAX_POSITION + 1) / this->gang_count_; // Width of each button region - if (width < 1 or width > this->gang_count_) // Invalid width - and prevents division by zero + //Calculate button number Change to round up insted of truncate (integer division) + const uint8_t width = (TOUCH_MAX_POSITION + gang_count_) / this->gang_count_; // Width of each button region + if (width < 1) // Invalid width - and prevents division by zero removed "width > gang_count_" issue with 2 gang return 0; const uint8_t button = std::min( static_cast((position / width) + 1), // Convert position to button index From 01097717319c9150e885646ed6ee913369672ef5 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Thu, 26 Dec 2024 20:36:19 +0000 Subject: [PATCH 026/109] Bump version to 2024.12.20 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 035e90a..2d5323d 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.19 +2024.12.20 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 5803b9d..a705cbf 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.19 +version: 2024.12.20 From 3cf6a11bc743f43d37d526c12b9929313706423a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 21:59:31 +0100 Subject: [PATCH 027/109] Add Speaker amplifier switch and removed click sound from substitutions --- ...imate-Easy-ESPHome_addon_media_player.yaml | 16 +++++++++ ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 35 ++++++++++--------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml index 32f9b74..6863f29 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml @@ -33,6 +33,10 @@ media_player: i2s_comm_fmt: msb # Experimental - It was 'lsb' until v2024.12.12 dac_type: external mode: mono + mute_pin: + number: GPIO26 + inverted: true + allow_other_uses: true script: - id: !extend dump_config @@ -48,4 +52,16 @@ script: // Identify itself ESP_LOGCONFIG("addon_media_player", "Add-on Media Player installed"); + +switch: + - id: sw_speaker_amplifier + name: Speaker - Amplifier + platform: gpio + pin: + number: GPIO26 + inverted: true + allow_other_uses: true + restore_mode: RESTORE_DEFAULT_ON + internal: true + entity_category: config ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index 9d58bac..be25a23 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -16,21 +16,6 @@ substitutions: # d=32 (32nd note), o=5 (octave 5), b=100 (tempo 100) tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound - click_sound: |- - [ - 0x01,0x02,0x04,0x06,0x07,0x08,0x08,0x06,0x01,0xFA,0xF4,0xEF,0xEE,0xF1,0xF7,0xFF,0x07,0x0E, - 0x11,0x11,0x10,0x0C,0x06,0xFF,0xF8,0xF1,0xEC,0xEA,0xEC,0xF2,0xF9,0xFF,0x05,0x0A,0x10,0x14, - 0x17,0x17,0x14,0x0B,0xFD,0xED,0xE0,0xD9,0xDB,0xE6,0xF7,0x0A,0x19,0x20,0x1E,0x14,0x05,0xF4, - 0xE5,0xDF,0xE4,0xF4,0x0C,0x24,0x36,0x3D,0x35,0x20,0xFF,0xDD,0xC0,0xAE,0xA9,0xB0,0xC4,0xE0, - 0x03,0x26,0x48,0x62,0x70,0x6D,0x59,0x35,0x08,0xD8,0xAC,0x8D,0x80,0x85,0x9C,0xC1,0xF0,0x21, - 0x4E,0x6F,0x7F,0x7A,0x63,0x3D,0x0F,0xE0,0xB7,0x9B,0x90,0x96,0xAC,0xCE,0xF6,0x1D,0x3C,0x50, - 0x55,0x4D,0x3A,0x20,0x04,0xEC,0xD8,0xCC,0xC9,0xCD,0xD8,0xE8,0xF9,0x0A,0x17,0x1F,0x20,0x1C, - 0x12,0x07,0xFC,0xF2,0xEC,0xEB,0xED,0xF3,0xFA,0x02,0x0A,0x10,0x12,0x12,0x0E,0x07,0xFE,0xF5, - 0xED,0xEA,0xEB,0xEF,0xF7,0x00,0x0A,0x10,0x13,0x12,0x0F,0x09,0x02,0xFB,0xF5,0xF3,0xF2,0xF3, - 0xF6,0xFB,0xFF,0x03,0x05,0x07,0x08,0x07,0x05,0x03,0x01,0xFF,0xFE,0xFC,0xFB,0xFB,0xFC,0xFC, - 0xFD,0xFE,0xFF,0x00,0x01,0x02,0x02,0x01 - ] - packages: core_hw_audio: !include TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml @@ -104,7 +89,25 @@ script: then: - speaker.play: id: speaker_embedded - data: !lambda return std::vector(${click_sound}); + data: [0x01,0x02,0x04,0x06,0x07,0x08,0x08,0x06,0x01,0xFA,0xF4, + 0xEF,0xEE,0xF1,0xF7,0xFF,0x07,0x0E,0x11,0x11,0x10,0x0C, + 0x06,0xFF,0xF8,0xF1,0xEC,0xEA,0xEC,0xF2,0xF9,0xFF,0x05, + 0x0A,0x10,0x14,0x17,0x17,0x14,0x0B,0xFD,0xED,0xE0,0xD9, + 0xDB,0xE6,0xF7,0x0A,0x19,0x20,0x1E,0x14,0x05,0xF4,0xE5, + 0xDF,0xE4,0xF4,0x0C,0x24,0x36,0x3D,0x35,0x20,0xFF,0xDD, + 0xC0,0xAE,0xA9,0xB0,0xC4,0xE0,0x03,0x26,0x48,0x62,0x70, + 0x6D,0x59,0x35,0x08,0xD8,0xAC,0x8D,0x80,0x85,0x9C,0xC1, + 0xF0,0x21,0x4E,0x6F,0x7F,0x7A,0x63,0x3D,0x0F,0xE0,0xB7, + 0x9B,0x90,0x96,0xAC,0xCE,0xF6,0x1D,0x3C,0x50,0x55,0x4D, + 0x3A,0x20,0x04,0xEC,0xD8,0xCC,0xC9,0xCD,0xD8,0xE8,0xF9, + 0x0A,0x17,0x1F,0x20,0x1C,0x12,0x07,0xFC,0xF2,0xEC,0xEB, + 0xED,0xF3,0xFA,0x02,0x0A,0x10,0x12,0x12,0x0E,0x07,0xFE, + 0xF5,0xED,0xEA,0xEB,0xEF,0xF7,0x00,0x0A,0x10,0x13,0x12, + 0x0F,0x09,0x02,0xFB,0xF5,0xF3,0xF2,0xF3,0xF6,0xFB,0xFF, + 0x03,0x05,0x07,0x08,0x07,0x05,0x03,0x01,0xFF,0xFE,0xFC, + 0xFB,0xFB,0xFC,0xFC,0xFD,0xFE,0xFF,0x00,0x01,0x02,0x02, + 0x01] + - wait_until: condition: not: From fa2c5dcc29a6887b262e60488f27fcc5270305b7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:01:56 +0100 Subject: [PATCH 028/109] Lint --- ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml index 6863f29..5d0dd7d 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml @@ -34,9 +34,9 @@ media_player: dac_type: external mode: mono mute_pin: - number: GPIO26 - inverted: true - allow_other_uses: true + number: GPIO26 + inverted: true + allow_other_uses: true script: - id: !extend dump_config From 47744c7144a857056cffa4343678a244db347f71 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:06:09 +0100 Subject: [PATCH 029/109] More changes covered by build test --- .github/workflows/validate_esphome_beta.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 917dedb..c59f192 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -16,12 +16,14 @@ on: # yamllint disable-line rule:truthy pull_request: paths: - "*.yaml" - - "ESPHome/*.yaml" - - ".test/*.yaml" - "*.h" - "*.c" - "*.cpp" - "*.py" + - ".test/*.*" + - "components/*.*" + - "components/tx_ultimate_easy/*.*" + - "ESPHome/*.*" workflow_dispatch: concurrency: From f8fa9a236314cf6da01591add7fae79054ca33ec Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:08:10 +0100 Subject: [PATCH 030/109] Lint --- ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index be25a23..d051c0e 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -89,24 +89,24 @@ script: then: - speaker.play: id: speaker_embedded - data: [0x01,0x02,0x04,0x06,0x07,0x08,0x08,0x06,0x01,0xFA,0xF4, - 0xEF,0xEE,0xF1,0xF7,0xFF,0x07,0x0E,0x11,0x11,0x10,0x0C, - 0x06,0xFF,0xF8,0xF1,0xEC,0xEA,0xEC,0xF2,0xF9,0xFF,0x05, - 0x0A,0x10,0x14,0x17,0x17,0x14,0x0B,0xFD,0xED,0xE0,0xD9, - 0xDB,0xE6,0xF7,0x0A,0x19,0x20,0x1E,0x14,0x05,0xF4,0xE5, - 0xDF,0xE4,0xF4,0x0C,0x24,0x36,0x3D,0x35,0x20,0xFF,0xDD, - 0xC0,0xAE,0xA9,0xB0,0xC4,0xE0,0x03,0x26,0x48,0x62,0x70, - 0x6D,0x59,0x35,0x08,0xD8,0xAC,0x8D,0x80,0x85,0x9C,0xC1, - 0xF0,0x21,0x4E,0x6F,0x7F,0x7A,0x63,0x3D,0x0F,0xE0,0xB7, - 0x9B,0x90,0x96,0xAC,0xCE,0xF6,0x1D,0x3C,0x50,0x55,0x4D, - 0x3A,0x20,0x04,0xEC,0xD8,0xCC,0xC9,0xCD,0xD8,0xE8,0xF9, - 0x0A,0x17,0x1F,0x20,0x1C,0x12,0x07,0xFC,0xF2,0xEC,0xEB, - 0xED,0xF3,0xFA,0x02,0x0A,0x10,0x12,0x12,0x0E,0x07,0xFE, - 0xF5,0xED,0xEA,0xEB,0xEF,0xF7,0x00,0x0A,0x10,0x13,0x12, - 0x0F,0x09,0x02,0xFB,0xF5,0xF3,0xF2,0xF3,0xF6,0xFB,0xFF, - 0x03,0x05,0x07,0x08,0x07,0x05,0x03,0x01,0xFF,0xFE,0xFC, - 0xFB,0xFB,0xFC,0xFC,0xFD,0xFE,0xFF,0x00,0x01,0x02,0x02, - 0x01] + data: [ 0x01, 0x02, 0x04, 0x06, 0x07, 0x08, 0x08, 0x06, 0x01, 0xFA, 0xF4, + 0xEF, 0xEE, 0xF1, 0xF7, 0xFF, 0x07, 0x0E, 0x11, 0x11, 0x10, 0x0C, + 0x06, 0xFF, 0xF8, 0xF1, 0xEC, 0xEA, 0xEC, 0xF2, 0xF9, 0xFF, 0x05, + 0x0A, 0x10, 0x14, 0x17, 0x17, 0x14, 0x0B, 0xFD, 0xED, 0xE0, 0xD9, + 0xDB, 0xE6, 0xF7, 0x0A, 0x19, 0x20, 0x1E, 0x14, 0x05, 0xF4, 0xE5, + 0xDF, 0xE4, 0xF4, 0x0C, 0x24, 0x36, 0x3D, 0x35, 0x20, 0xFF, 0xDD, + 0xC0, 0xAE, 0xA9, 0xB0, 0xC4, 0xE0, 0x03, 0x26, 0x48, 0x62, 0x70, + 0x6D, 0x59, 0x35, 0x08, 0xD8, 0xAC, 0x8D, 0x80, 0x85, 0x9C, 0xC1, + 0xF0, 0x21, 0x4E, 0x6F, 0x7F, 0x7A, 0x63, 0x3D, 0x0F, 0xE0, 0xB7, + 0x9B, 0x90, 0x96, 0xAC, 0xCE, 0xF6, 0x1D, 0x3C, 0x50, 0x55, 0x4D, + 0x3A, 0x20, 0x04, 0xEC, 0xD8, 0xCC, 0xC9, 0xCD, 0xD8, 0xE8, 0xF9, + 0x0A, 0x17, 0x1F, 0x20, 0x1C, 0x12, 0x07, 0xFC, 0xF2, 0xEC, 0xEB, + 0xED, 0xF3, 0xFA, 0x02, 0x0A, 0x10, 0x12, 0x12, 0x0E, 0x07, 0xFE, + 0xF5, 0xED, 0xEA, 0xEB, 0xEF, 0xF7, 0x00, 0x0A, 0x10, 0x13, 0x12, + 0x0F, 0x09, 0x02, 0xFB, 0xF5, 0xF3, 0xF2, 0xF3, 0xF6, 0xFB, 0xFF, + 0x03, 0x05, 0x07, 0x08, 0x07, 0x05, 0x03, 0x01, 0xFF, 0xFE, 0xFC, + 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x02, + 0x01 ] - wait_until: condition: From 493dcb0abb2381f2b6b5714cdb413495d33c7ea6 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:09:48 +0100 Subject: [PATCH 031/109] Lint --- ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index d051c0e..0728da7 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -89,24 +89,26 @@ script: then: - speaker.play: id: speaker_embedded - data: [ 0x01, 0x02, 0x04, 0x06, 0x07, 0x08, 0x08, 0x06, 0x01, 0xFA, 0xF4, - 0xEF, 0xEE, 0xF1, 0xF7, 0xFF, 0x07, 0x0E, 0x11, 0x11, 0x10, 0x0C, - 0x06, 0xFF, 0xF8, 0xF1, 0xEC, 0xEA, 0xEC, 0xF2, 0xF9, 0xFF, 0x05, - 0x0A, 0x10, 0x14, 0x17, 0x17, 0x14, 0x0B, 0xFD, 0xED, 0xE0, 0xD9, - 0xDB, 0xE6, 0xF7, 0x0A, 0x19, 0x20, 0x1E, 0x14, 0x05, 0xF4, 0xE5, - 0xDF, 0xE4, 0xF4, 0x0C, 0x24, 0x36, 0x3D, 0x35, 0x20, 0xFF, 0xDD, - 0xC0, 0xAE, 0xA9, 0xB0, 0xC4, 0xE0, 0x03, 0x26, 0x48, 0x62, 0x70, - 0x6D, 0x59, 0x35, 0x08, 0xD8, 0xAC, 0x8D, 0x80, 0x85, 0x9C, 0xC1, - 0xF0, 0x21, 0x4E, 0x6F, 0x7F, 0x7A, 0x63, 0x3D, 0x0F, 0xE0, 0xB7, - 0x9B, 0x90, 0x96, 0xAC, 0xCE, 0xF6, 0x1D, 0x3C, 0x50, 0x55, 0x4D, - 0x3A, 0x20, 0x04, 0xEC, 0xD8, 0xCC, 0xC9, 0xCD, 0xD8, 0xE8, 0xF9, - 0x0A, 0x17, 0x1F, 0x20, 0x1C, 0x12, 0x07, 0xFC, 0xF2, 0xEC, 0xEB, - 0xED, 0xF3, 0xFA, 0x02, 0x0A, 0x10, 0x12, 0x12, 0x0E, 0x07, 0xFE, - 0xF5, 0xED, 0xEA, 0xEB, 0xEF, 0xF7, 0x00, 0x0A, 0x10, 0x13, 0x12, - 0x0F, 0x09, 0x02, 0xFB, 0xF5, 0xF3, 0xF2, 0xF3, 0xF6, 0xFB, 0xFF, - 0x03, 0x05, 0x07, 0x08, 0x07, 0x05, 0x03, 0x01, 0xFF, 0xFE, 0xFC, - 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x02, - 0x01 ] + data: [ + 0x01, 0x02, 0x04, 0x06, 0x07, 0x08, 0x08, 0x06, 0x01, 0xFA, 0xF4, + 0xEF, 0xEE, 0xF1, 0xF7, 0xFF, 0x07, 0x0E, 0x11, 0x11, 0x10, 0x0C, + 0x06, 0xFF, 0xF8, 0xF1, 0xEC, 0xEA, 0xEC, 0xF2, 0xF9, 0xFF, 0x05, + 0x0A, 0x10, 0x14, 0x17, 0x17, 0x14, 0x0B, 0xFD, 0xED, 0xE0, 0xD9, + 0xDB, 0xE6, 0xF7, 0x0A, 0x19, 0x20, 0x1E, 0x14, 0x05, 0xF4, 0xE5, + 0xDF, 0xE4, 0xF4, 0x0C, 0x24, 0x36, 0x3D, 0x35, 0x20, 0xFF, 0xDD, + 0xC0, 0xAE, 0xA9, 0xB0, 0xC4, 0xE0, 0x03, 0x26, 0x48, 0x62, 0x70, + 0x6D, 0x59, 0x35, 0x08, 0xD8, 0xAC, 0x8D, 0x80, 0x85, 0x9C, 0xC1, + 0xF0, 0x21, 0x4E, 0x6F, 0x7F, 0x7A, 0x63, 0x3D, 0x0F, 0xE0, 0xB7, + 0x9B, 0x90, 0x96, 0xAC, 0xCE, 0xF6, 0x1D, 0x3C, 0x50, 0x55, 0x4D, + 0x3A, 0x20, 0x04, 0xEC, 0xD8, 0xCC, 0xC9, 0xCD, 0xD8, 0xE8, 0xF9, + 0x0A, 0x17, 0x1F, 0x20, 0x1C, 0x12, 0x07, 0xFC, 0xF2, 0xEC, 0xEB, + 0xED, 0xF3, 0xFA, 0x02, 0x0A, 0x10, 0x12, 0x12, 0x0E, 0x07, 0xFE, + 0xF5, 0xED, 0xEA, 0xEB, 0xEF, 0xF7, 0x00, 0x0A, 0x10, 0x13, 0x12, + 0x0F, 0x09, 0x02, 0xFB, 0xF5, 0xF3, 0xF2, 0xF3, 0xF6, 0xFB, 0xFF, + 0x03, 0x05, 0x07, 0x08, 0x07, 0x05, 0x03, 0x01, 0xFF, 0xFE, 0xFC, + 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x02, + 0x01 + ] - wait_until: condition: From d656f4b73f2845fc7b05cb24f619c0a77223c881 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:13:27 +0100 Subject: [PATCH 032/109] Lint --- ...X-Ultimate-Easy-ESPHome_addon_speaker.yaml | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index 0728da7..bbdacec 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -90,25 +90,24 @@ script: - speaker.play: id: speaker_embedded data: [ - 0x01, 0x02, 0x04, 0x06, 0x07, 0x08, 0x08, 0x06, 0x01, 0xFA, 0xF4, - 0xEF, 0xEE, 0xF1, 0xF7, 0xFF, 0x07, 0x0E, 0x11, 0x11, 0x10, 0x0C, - 0x06, 0xFF, 0xF8, 0xF1, 0xEC, 0xEA, 0xEC, 0xF2, 0xF9, 0xFF, 0x05, - 0x0A, 0x10, 0x14, 0x17, 0x17, 0x14, 0x0B, 0xFD, 0xED, 0xE0, 0xD9, - 0xDB, 0xE6, 0xF7, 0x0A, 0x19, 0x20, 0x1E, 0x14, 0x05, 0xF4, 0xE5, - 0xDF, 0xE4, 0xF4, 0x0C, 0x24, 0x36, 0x3D, 0x35, 0x20, 0xFF, 0xDD, - 0xC0, 0xAE, 0xA9, 0xB0, 0xC4, 0xE0, 0x03, 0x26, 0x48, 0x62, 0x70, - 0x6D, 0x59, 0x35, 0x08, 0xD8, 0xAC, 0x8D, 0x80, 0x85, 0x9C, 0xC1, - 0xF0, 0x21, 0x4E, 0x6F, 0x7F, 0x7A, 0x63, 0x3D, 0x0F, 0xE0, 0xB7, - 0x9B, 0x90, 0x96, 0xAC, 0xCE, 0xF6, 0x1D, 0x3C, 0x50, 0x55, 0x4D, - 0x3A, 0x20, 0x04, 0xEC, 0xD8, 0xCC, 0xC9, 0xCD, 0xD8, 0xE8, 0xF9, - 0x0A, 0x17, 0x1F, 0x20, 0x1C, 0x12, 0x07, 0xFC, 0xF2, 0xEC, 0xEB, - 0xED, 0xF3, 0xFA, 0x02, 0x0A, 0x10, 0x12, 0x12, 0x0E, 0x07, 0xFE, - 0xF5, 0xED, 0xEA, 0xEB, 0xEF, 0xF7, 0x00, 0x0A, 0x10, 0x13, 0x12, - 0x0F, 0x09, 0x02, 0xFB, 0xF5, 0xF3, 0xF2, 0xF3, 0xF6, 0xFB, 0xFF, - 0x03, 0x05, 0x07, 0x08, 0x07, 0x05, 0x03, 0x01, 0xFF, 0xFE, 0xFC, - 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x02, - 0x01 - ] + 0x01, 0x02, 0x04, 0x06, 0x07, 0x08, 0x08, 0x06, 0x01, 0xFA, 0xF4, + 0xEF, 0xEE, 0xF1, 0xF7, 0xFF, 0x07, 0x0E, 0x11, 0x11, 0x10, 0x0C, + 0x06, 0xFF, 0xF8, 0xF1, 0xEC, 0xEA, 0xEC, 0xF2, 0xF9, 0xFF, 0x05, + 0x0A, 0x10, 0x14, 0x17, 0x17, 0x14, 0x0B, 0xFD, 0xED, 0xE0, 0xD9, + 0xDB, 0xE6, 0xF7, 0x0A, 0x19, 0x20, 0x1E, 0x14, 0x05, 0xF4, 0xE5, + 0xDF, 0xE4, 0xF4, 0x0C, 0x24, 0x36, 0x3D, 0x35, 0x20, 0xFF, 0xDD, + 0xC0, 0xAE, 0xA9, 0xB0, 0xC4, 0xE0, 0x03, 0x26, 0x48, 0x62, 0x70, + 0x6D, 0x59, 0x35, 0x08, 0xD8, 0xAC, 0x8D, 0x80, 0x85, 0x9C, 0xC1, + 0xF0, 0x21, 0x4E, 0x6F, 0x7F, 0x7A, 0x63, 0x3D, 0x0F, 0xE0, 0xB7, + 0x9B, 0x90, 0x96, 0xAC, 0xCE, 0xF6, 0x1D, 0x3C, 0x50, 0x55, 0x4D, + 0x3A, 0x20, 0x04, 0xEC, 0xD8, 0xCC, 0xC9, 0xCD, 0xD8, 0xE8, 0xF9, + 0x0A, 0x17, 0x1F, 0x20, 0x1C, 0x12, 0x07, 0xFC, 0xF2, 0xEC, 0xEB, + 0xED, 0xF3, 0xFA, 0x02, 0x0A, 0x10, 0x12, 0x12, 0x0E, 0x07, 0xFE, + 0xF5, 0xED, 0xEA, 0xEB, 0xEF, 0xF7, 0x00, 0x0A, 0x10, 0x13, 0x12, + 0x0F, 0x09, 0x02, 0xFB, 0xF5, 0xF3, 0xF2, 0xF3, 0xF6, 0xFB, 0xFF, + 0x03, 0x05, 0x07, 0x08, 0x07, 0x05, 0x03, 0x01, 0xFF, 0xFE, 0xFC, + 0xFB, 0xFB, 0xFC, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01, 0x02, 0x02, + 0x01] - wait_until: condition: From 45b30d30fac5d0dd5d5d0c497b5a6227862ba105 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 22:17:45 +0100 Subject: [PATCH 033/109] Removed reference to experimental i2s format --- ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml index 5d0dd7d..a922cbe 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml @@ -30,7 +30,7 @@ media_player: platform: i2s_audio i2s_dout_pin: GPIO15 i2s_audio_id: if_i2s_audio - i2s_comm_fmt: msb # Experimental - It was 'lsb' until v2024.12.12 + i2s_comm_fmt: msb dac_type: external mode: mono mute_pin: From d4a18dc595ae50dc5fd5f7f371b2077d1b1dbe92 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Dec 2024 23:57:21 +0100 Subject: [PATCH 034/109] Play sound at volume change --- ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml index bbdacec..e416737 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml @@ -60,6 +60,14 @@ number: - speaker.volume_set: id: speaker_embedded volume: !lambda return x/100.0f; + - if: + condition: + - lambda: 'return x > 0;' + - lambda: 'return "${tone_volume_change}" != "none";' + then: + - rtttl.play: + id: rtttl_speaker + rtttl: "${tone_volume_change}" rtttl: - id: rtttl_speaker From e69873cab5dba325fb511f952e12299251333b0c Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:42:41 +0100 Subject: [PATCH 035/109] Create standard package --- .github/workflows/validate_esphome_beta.yml | 121 ++++++++++- .test/esphome_ard_basic.yaml | 3 +- ..._proxy.yaml => esphome_ard_ble_proxy.yaml} | 5 + .test/esphome_ard_core.yaml | 8 + .test/esphome_idf53_basic.yaml | 11 + ...roxy.yaml => esphome_idf53_ble_proxy.yaml} | 1 + .test/esphome_idf53_core.yaml | 10 + .test/esphome_idf53_media_player.yaml | 12 ++ .test/esphome_idf_basic.yaml | 9 + .test/esphome_idf_ble_proxy.yaml | 10 + .test/esphome_idf_core.yaml | 8 + .test/esphome_idf_media_player.yaml | 10 + ...Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 5 +- ...imate-Easy-ESPHome_addon_media_player.yaml | 11 +- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 59 +++--- ...Ultimate-Easy-ESPHome_core_hw_buttons.yaml | 17 +- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 67 ++----- ...X-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 17 +- .../TX-Ultimate-Easy-ESPHome_standard.yaml | 72 +++++++ ...imate-Easy-ESPHome_standard_hw_audio.yaml} | 10 +- ...mate-Easy-ESPHome_standard_hw_relays.yaml} | 189 ++++++++++++------ ...e-Easy-ESPHome_standard_hw_vibration.yaml} | 33 +-- ...timate-Easy-ESPHome_standard_speaker.yaml} | 17 +- TX-Ultimate-Easy-ESPHome.yaml | 4 +- 24 files changed, 507 insertions(+), 202 deletions(-) rename .test/{esphome_idf_bluetooth_proxy.yaml => esphome_ard_ble_proxy.yaml} (60%) create mode 100644 .test/esphome_ard_core.yaml create mode 100644 .test/esphome_idf53_basic.yaml rename .test/{esphome_idf53_bluetooth_proxy.yaml => esphome_idf53_ble_proxy.yaml} (77%) create mode 100644 .test/esphome_idf53_core.yaml create mode 100644 .test/esphome_idf53_media_player.yaml create mode 100644 .test/esphome_idf_basic.yaml create mode 100644 .test/esphome_idf_ble_proxy.yaml create mode 100644 .test/esphome_idf_core.yaml create mode 100644 .test/esphome_idf_media_player.yaml create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml rename ESPHome/{TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml => TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml} (83%) rename ESPHome/{TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml => TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml} (82%) rename ESPHome/{TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml => TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml} (85%) rename ESPHome/{TX-Ultimate-Easy-ESPHome_addon_speaker.yaml => TX-Ultimate-Easy-ESPHome_standard_speaker.yaml} (91%) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index c59f192..6367c31 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -49,36 +49,135 @@ jobs: - name: Validate YAML files run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} + - build_basic: - name: Basic + build_ard_core: + name: Core (Arduino) + needs: code_scan runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Core (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_core.yaml" + version: beta + + build_idf_core: + name: Core (IDF) + needs: code_scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Core (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_core.yaml" + version: beta + + build_idf53_core: + name: Core (IDFv5.3) + needs: code_scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Core (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_core.yaml" + version: beta + + build_ard_basic: + name: Basic (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Basic (Arduino) uses: esphome/build-action@main with: yaml-file: ".test/esphome_ard_basic.yaml" version: beta - build_bluetooth_proxy_4: - name: Bluetooth Proxy (IDF) + build_idf_basic: + name: Core (IDF) + needs: build_idf_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Basic (IDF) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf_basic.yaml" version: beta - build_bluetooth_proxy_53: - name: Bluetooth Proxy (IDF v5.3) + build_idf53_basic: + name: Basic (IDFv5.3) + needs: build_idf53_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Basic (IDFv5.3) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf53_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf53_basic.yaml" + version: beta + + build_ard_ble_proxy: + name: Bluetooth Proxy (Ard) + needs: build_ard_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (Ard) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_ble_proxy.yaml" + version: beta + + build_idf_ble_proxy: + name: Bluetooth Proxy (IDF) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_ble_proxy.yaml" + version: beta + + build_idf53_ble_proxy: + name: Bluetooth Proxy (IDFv5.3) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_ble_proxy.yaml" + version: beta + + build_idf_media_player: + name: Media Player (IDF) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Media Player (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_media_player.yaml" + version: beta + + build_idf53_media_player: + name: Media Player (IDFv5.3) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Media Player (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_media_player.yaml" version: beta ... diff --git a/.test/esphome_ard_basic.yaml b/.test/esphome_ard_basic.yaml index ed32a8f..91753ec 100644 --- a/.test/esphome_ard_basic.yaml +++ b/.test/esphome_ard_basic.yaml @@ -1,6 +1,7 @@ --- packages: - basic_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Basic package + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml esp32: framework: diff --git a/.test/esphome_idf_bluetooth_proxy.yaml b/.test/esphome_ard_ble_proxy.yaml similarity index 60% rename from .test/esphome_idf_bluetooth_proxy.yaml rename to .test/esphome_ard_ble_proxy.yaml index 3e434a5..e21e328 100644 --- a/.test/esphome_idf_bluetooth_proxy.yaml +++ b/.test/esphome_ard_ble_proxy.yaml @@ -1,5 +1,10 @@ --- packages: core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml + +esp32: + framework: + type: arduino ... diff --git a/.test/esphome_ard_core.yaml b/.test/esphome_ard_core.yaml new file mode 100644 index 0000000..bee25b3 --- /dev/null +++ b/.test/esphome_ard_core.yaml @@ -0,0 +1,8 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + +esp32: + framework: + type: arduino +... diff --git a/.test/esphome_idf53_basic.yaml b/.test/esphome_idf53_basic.yaml new file mode 100644 index 0000000..44ebb3b --- /dev/null +++ b/.test/esphome_idf53_basic.yaml @@ -0,0 +1,11 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 +... diff --git a/.test/esphome_idf53_bluetooth_proxy.yaml b/.test/esphome_idf53_ble_proxy.yaml similarity index 77% rename from .test/esphome_idf53_bluetooth_proxy.yaml rename to .test/esphome_idf53_ble_proxy.yaml index a8d3868..d4aa126 100644 --- a/.test/esphome_idf53_bluetooth_proxy.yaml +++ b/.test/esphome_idf53_ble_proxy.yaml @@ -1,6 +1,7 @@ --- packages: core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml esp32: diff --git a/.test/esphome_idf53_core.yaml b/.test/esphome_idf53_core.yaml new file mode 100644 index 0000000..438146c --- /dev/null +++ b/.test/esphome_idf53_core.yaml @@ -0,0 +1,10 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 +... diff --git a/.test/esphome_idf53_media_player.yaml b/.test/esphome_idf53_media_player.yaml new file mode 100644 index 0000000..c8c4414 --- /dev/null +++ b/.test/esphome_idf53_media_player.yaml @@ -0,0 +1,12 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 +... diff --git a/.test/esphome_idf_basic.yaml b/.test/esphome_idf_basic.yaml new file mode 100644 index 0000000..9f20465 --- /dev/null +++ b/.test/esphome_idf_basic.yaml @@ -0,0 +1,9 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + +esp32: + framework: + type: esp-idf +... diff --git a/.test/esphome_idf_ble_proxy.yaml b/.test/esphome_idf_ble_proxy.yaml new file mode 100644 index 0000000..3aeba92 --- /dev/null +++ b/.test/esphome_idf_ble_proxy.yaml @@ -0,0 +1,10 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml + +esp32: + framework: + type: esp-idf +... diff --git a/.test/esphome_idf_core.yaml b/.test/esphome_idf_core.yaml new file mode 100644 index 0000000..3daf403 --- /dev/null +++ b/.test/esphome_idf_core.yaml @@ -0,0 +1,8 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + +esp32: + framework: + type: esp-idf +... diff --git a/.test/esphome_idf_media_player.yaml b/.test/esphome_idf_media_player.yaml new file mode 100644 index 0000000..1c2697b --- /dev/null +++ b/.test/esphome_idf_media_player.yaml @@ -0,0 +1,10 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml + +esp32: + framework: + type: esp-idf +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 9f644a8..1346efb 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -19,8 +19,9 @@ esphome: - -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY script: - - id: !extend dump_config + - id: !extend dump_config_list_packages then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) @@ -28,5 +29,5 @@ script: #endif // Identify itself - ESP_LOGCONFIG("addon_ble_proxy", "Add-on BLE Proxy installed"); + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - BLE Proxy"); ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml index a922cbe..d6985fb 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml @@ -12,7 +12,7 @@ #################################################################################################### --- packages: - core_hw_audio: !include TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml + standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml esp32: framework: @@ -39,19 +39,20 @@ media_player: allow_other_uses: true script: - - id: !extend dump_config + - id: !extend dump_config_list_packages then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif - #if !defined(TX_ULTIMATE_EASY_CORE_HW_AUDIO) - #error "The package TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml is required." + #if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO) + #error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required." #endif // Identify itself - ESP_LOGCONFIG("addon_media_player", "Add-on Media Player installed"); + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - Media Player"); switch: - id: sw_speaker_amplifier diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index c5749a7..843ca1a 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -29,11 +29,9 @@ substitutions: packages: # yamllint disable rule:colons - core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml - core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml - core_hw_relays: !include TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml - core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml - core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml + core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml + core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml + core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # yamllint enable rule:colons api: @@ -60,15 +58,6 @@ binary_sensor: ESP_LOGCONFIG("core", "Pending restart: No"); - script.execute: dump_config_caller -button: - - id: bt_restart - name: Restart - internal: false - platform: restart - -captive_portal: - id: ap_captive_portal - esp32: board: esp32dev # adafruit_feather_esp32_v2 # esp32dev flash_size: 8MB @@ -79,6 +68,9 @@ esphome: name: ${name} friendly_name: ${friendly_name} comment: TX Ultimate Easy + project: + name: "edwardtfn.tx_ultimate_easy" + version: ${version} platformio_options: build_flags: - -D TX_ULTIMATE_EASY_CORE @@ -113,9 +105,6 @@ globals: max_restore_data_length: 3 # initial_value: "''" -improv_serial: - id: serial_improv - logger: level: DEBUG @@ -188,9 +177,7 @@ script: ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str()); ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str()); - // Version information - ESP_LOGCONFIG("core", "ESPHome builder: %s", esphome_fw_version->state.c_str()); - ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); + dump_config_versions->execute(); // Framework detection #ifdef USE_ARDUINO @@ -218,6 +205,25 @@ script: then: - delay: ${DUMP_CONFIG_CALLER_DELAY} - script.execute: dump_config + - script.wait: dump_config + - script.execute: dump_config_list_packages + + - id: dump_config_list_packages + mode: restart + then: + - script.wait: dump_config + - lambda: |- + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, "Installed packages:"); + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core"); + + - id: dump_config_versions + mode: restart + then: + - lambda: |- + // Version information + ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); - id: publish_device_info mode: restart @@ -275,12 +281,6 @@ select: tx_ultimate->set_gang_count(id(gang_count)); text_sensor: - - id: esphome_fw_version - name: ESPHome Version - platform: version - entity_category: diagnostic - internal: false - - id: tx_fw_version name: TX Ultimate Easy Firmware Version platform: template @@ -317,13 +317,6 @@ text_sensor: } return result; -time: - - id: time_source - platform: homeassistant - -web_server: - wifi: id: wifi_component - ap: ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml index 446e344..d93d70b 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml @@ -208,11 +208,6 @@ script: - id: !extend dump_config then: - lambda: |- - // Check for requirements - #if !defined(TX_ULTIMATE_EASY_CORE) - #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." - #endif - // Button's actions ESP_LOGCONFIG("core_hw_buttons", "Button%s action%s:", id(gang_count_plural_suffix).c_str(), @@ -233,6 +228,18 @@ script: ? sl_button_4_action->state.c_str() : "Unknown"); + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - Buttons"); + - id: !extend touch_on_multi_touch_release then: - script.execute: buttons_release diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 219e354..62579f7 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -443,64 +443,9 @@ script: light_us_right->set_internal(!id(is_us_model)); light_us_top->set_internal(!id(is_us_model)); - // LED Group Assignment: - // - For US model: gb_lights_1 = left side LEDs, gb_lights_2 = right side LEDs - // - For EU model: gb_lights_1 = bottom LEDs, gb_lights_2 = top LEDs - // Gang configurations determine which LED segments are active - switch (id(gang_count)) { - case 1: // 1 Gang - if (id(is_us_model)) { - id(gb_lights_1) = { light_us_rl_1_1_left }; - id(gb_lights_2) = { light_us_rl_1_1_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_1_bottom }; - id(gb_lights_2) = { light_eu_rl_1_1_top }; - } - break; - case 2: // 2 Gang - if (id(is_us_model)) { - id(gb_lights_1) = { light_us_rl_1_2_left, light_us_rl_2_2_left }; - id(gb_lights_2) = { light_us_rl_1_2_right, light_us_rl_2_2_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_2_bottom, light_eu_rl_2_2_bottom }; - id(gb_lights_2) = { light_eu_rl_1_2_top, light_eu_rl_2_2_top }; - } - break; - case 3: // 3 Gang - if (id(is_us_model)) { - id(gb_lights_1) = { light_us_rl_1_3_left, light_us_rl_2_3_left, light_us_rl_3_3_left }; - id(gb_lights_2) = { light_us_rl_1_3_right, light_us_rl_2_3_right, light_us_rl_3_3_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_3_bottom, light_eu_rl_2_3_bottom, light_eu_rl_3_3_bottom }; - id(gb_lights_2) = { light_eu_rl_1_3_top, light_eu_rl_2_3_top, light_eu_rl_3_3_top }; - } - break; - case 4: // 4 Gang - if (id(is_us_model)) { - id(gb_lights_1) = { light_us_rl_1_4_left, light_us_rl_2_4_left, - light_us_rl_3_4_left, light_us_rl_4_4_left }; - id(gb_lights_2) = { light_us_rl_1_4_right, light_us_rl_2_4_right, - light_us_rl_3_4_right, light_us_rl_4_4_right }; - } else { - id(gb_lights_1) = { light_eu_rl_1_4_bottom, light_eu_rl_2_4_bottom, - light_eu_rl_3_4_bottom, light_eu_rl_4_4_bottom }; - id(gb_lights_2) = { light_eu_rl_1_4_top, light_eu_rl_2_4_top, - light_eu_rl_3_4_top, light_eu_rl_4_4_top }; - } - break; - default: - ESP_LOGE("core_hw_leds", "Invalid gang count: %" PRIu8, id(gang_count)); - break; - } - - id: !extend dump_config then: - lambda: |- - // Check for requirements - #if !defined(TX_ULTIMATE_EASY_CORE) - #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." - #endif - // Relay's LEDs modes ESP_LOGCONFIG("core_hw_leds", "Relay%s LEDs mode%s:", id(gang_count_plural_suffix).c_str(), @@ -539,6 +484,18 @@ script: ESP_LOGCONFIG("core_hw_leds", " Sides: ${LIGHT_SIDES_RESTORE_MODE}"); ESP_LOGCONFIG("core_hw_leds", " Individual: ${LIGHT_INDIVIDUAL_RESTORE_MODE}"); + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - LEDs"); + - id: light_set_state mode: parallel parameters: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index f5c0157..8da5856 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -291,11 +291,6 @@ script: - id: !extend dump_config then: - lambda: |- - // Check for requirements - #if !defined(TX_ULTIMATE_EASY_CORE) - #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." - #endif - // Touch panel's state if (sw_touch_panel_power->state) ESP_LOGCONFIG("core_hw_touch", "Touch panel - Power: On"); @@ -303,6 +298,18 @@ script: ESP_LOGW("core_hw_touch", "Touch panel - Power: OFF"); ESP_LOGCONFIG("core_hw_touch", "Touch event duration: %.0fms", nr_touch_duration->state); + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core - Hardware - Touchpad"); + - id: touch_on_multi_touch_release mode: restart then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml new file mode 100644 index 0000000..0d9c0a7 --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml @@ -0,0 +1,72 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Standard (non-essential, but recommended packages) ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +packages: + # yamllint disable rule:colons + core_hw_relays: !include TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + core_hw_speaker: !include TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml + core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + # yamllint enable rule:colons + +button: + - id: bt_restart + name: Restart + internal: false + platform: restart + +captive_portal: + id: ap_captive_portal + +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_STANDARD + +script: + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard"); + + - id: !extend dump_config_versions + then: + - lambda: |- + // Version information + ESP_LOGCONFIG("standard", "ESPHome builder: %s", esphome_fw_version->state.c_str()); + +improv_serial: + id: serial_improv + +text_sensor: + - id: esphome_fw_version + name: ESPHome Version + platform: version + entity_category: diagnostic + internal: false + +time: + - id: time_source + platform: homeassistant + +web_server: + +wifi: + ap: +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml similarity index 83% rename from ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml index c9a91e2..3dcabb1 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome - Core - I2S Audio ##### +##### Purpose: ESPHome - Standard - I2S Audio ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### @@ -14,7 +14,7 @@ esphome: platformio_options: build_flags: - - -D TX_ULTIMATE_EASY_CORE_HW_AUDIO + - -D TX_ULTIMATE_EASY_STANDARD_HW_AUDIO i2s_audio: id: if_i2s_audio @@ -22,11 +22,15 @@ i2s_audio: i2s_lrclk_pin: GPIO4 script: - - id: !extend dump_config + - id: !extend dump_config_list_packages then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Audio"); ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml similarity index 82% rename from ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml index 7fa0809..432994f 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome Core - Hardware - Relays ##### +##### Purpose: ESPHome - Standard - Hardware - Relays ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### @@ -22,13 +22,17 @@ substitutions: esphome: platformio_options: build_flags: - - -D TX_ULTIMATE_EASY_CORE_HW_RELAYS + - -D TX_ULTIMATE_EASY_STANDARD_HW_RELAYS globals: - id: boot_initialization_relays type: bool restore_value: false initial_value: 'false' + - id: boot_initialization_relays_group_assignments + type: bool + restore_value: false + initial_value: 'false' - id: boot_initialization_relays_light_modes type: bool restore_value: false @@ -440,14 +444,17 @@ script: - id: boot_initialize_relays mode: restart then: + - script.execute: boot_initialize_relays_group_assignments - script.execute: boot_initialize_relays_light_modes - script.execute: boot_initialize_relays_relay_leds - script.execute: boot_initialize_relays_relay_modes + - script.wait: boot_initialize_relays_group_assignments - script.wait: boot_initialize_relays_light_modes - script.wait: boot_initialize_relays_relay_leds - script.wait: boot_initialize_relays_relay_modes - wait_until: condition: + - lambda: return id(boot_initialization_relays_group_assignments); - lambda: return id(boot_initialization_relays_light_modes); - lambda: return id(boot_initialization_relays_relay_leds); - lambda: return id(boot_initialization_relays_relay_modes); @@ -455,6 +462,61 @@ script: id: boot_initialization_relays value: 'true' + - id: boot_initialize_relays_group_assignments + mode: restart + then: + - lambda: |- + // LED Group Assignment: + // - For US model: gb_lights_1 = left side LEDs, gb_lights_2 = right side LEDs + // - For EU model: gb_lights_1 = bottom LEDs, gb_lights_2 = top LEDs + // Gang configurations determine which LED segments are active + switch (id(gang_count)) { + case 1: // 1 Gang + if (id(is_us_model)) { + id(gb_lights_1) = { light_us_rl_1_1_left }; + id(gb_lights_2) = { light_us_rl_1_1_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_1_bottom }; + id(gb_lights_2) = { light_eu_rl_1_1_top }; + } + break; + case 2: // 2 Gang + if (id(is_us_model)) { + id(gb_lights_1) = { light_us_rl_1_2_left, light_us_rl_2_2_left }; + id(gb_lights_2) = { light_us_rl_1_2_right, light_us_rl_2_2_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_2_bottom, light_eu_rl_2_2_bottom }; + id(gb_lights_2) = { light_eu_rl_1_2_top, light_eu_rl_2_2_top }; + } + break; + case 3: // 3 Gang + if (id(is_us_model)) { + id(gb_lights_1) = { light_us_rl_1_3_left, light_us_rl_2_3_left, light_us_rl_3_3_left }; + id(gb_lights_2) = { light_us_rl_1_3_right, light_us_rl_2_3_right, light_us_rl_3_3_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_3_bottom, light_eu_rl_2_3_bottom, light_eu_rl_3_3_bottom }; + id(gb_lights_2) = { light_eu_rl_1_3_top, light_eu_rl_2_3_top, light_eu_rl_3_3_top }; + } + break; + case 4: // 4 Gang + if (id(is_us_model)) { + id(gb_lights_1) = { light_us_rl_1_4_left, light_us_rl_2_4_left, + light_us_rl_3_4_left, light_us_rl_4_4_left }; + id(gb_lights_2) = { light_us_rl_1_4_right, light_us_rl_2_4_right, + light_us_rl_3_4_right, light_us_rl_4_4_right }; + } else { + id(gb_lights_1) = { light_eu_rl_1_4_bottom, light_eu_rl_2_4_bottom, + light_eu_rl_3_4_bottom, light_eu_rl_4_4_bottom }; + id(gb_lights_2) = { light_eu_rl_1_4_top, light_eu_rl_2_4_top, + light_eu_rl_3_4_top, light_eu_rl_4_4_top }; + } + break; + default: + ESP_LOGE("standard_hw_relays", "Invalid gang count: %" PRIu8, id(gang_count)); + break; + } + id(boot_initialization_relays_group_assignments) = true; + - id: boot_initialize_relays_light_modes mode: restart then: @@ -591,13 +653,13 @@ script: std::string select_state; bool toggle_relay = false; if (api_disconnected) { - ESP_LOGW("core_hw_relays", "Toggle relays:"); - ESP_LOGW("core_hw_relays", " API state: DISCONNECTED"); - ESP_LOGW("core_hw_relays", " Button: %" PRIu8, button); + ESP_LOGW("standard_hw_relays", "Toggle relays:"); + ESP_LOGW("standard_hw_relays", " API state: DISCONNECTED"); + ESP_LOGW("standard_hw_relays", " Button: %" PRIu8, button); } else { - ESP_LOGVV("core_hw_relays", "Toggle relays:"); - ESP_LOGVV("core_hw_relays", " API state: Connected"); - ESP_LOGVV("core_hw_relays", " Button: %" PRIu8, button); + ESP_LOGVV("standard_hw_relays", "Toggle relays:"); + ESP_LOGVV("standard_hw_relays", " API state: Connected"); + ESP_LOGVV("standard_hw_relays", " Button: %" PRIu8, button); } switch (button) { case ${BUTTON_1_ID}: @@ -630,67 +692,76 @@ script: break; } if (toggle_relay) { - ESP_LOGI("core_hw_relays", "Toggle relay %" PRIu8 ": (%s)", button, select_state.c_str()); + ESP_LOGI("standard_hw_relays", "Toggle relay %" PRIu8 ": (%s)", button, select_state.c_str()); } else if (not select_state.empty()) { - ESP_LOGV("core_hw_relays", "Ignoring toggle for relay %" PRIu8 ": action is '%s'", + ESP_LOGV("standard_hw_relays", "Ignoring toggle for relay %" PRIu8 ": action is '%s'", button, select_state.c_str()); } else { - ESP_LOGE("core_hw_relays", "No button action selected for button %" PRIu8, button); + ESP_LOGE("standard_hw_relays", "No button action selected for button %" PRIu8, button); } - id: !extend dump_config then: + - lambda: |- + // Relay's modes + ESP_LOGCONFIG("standard_hw_relays", "Relay%s mode%s:", + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); + ESP_LOGCONFIG("standard_hw_relays", " Relay 1: %s", sl_relay_1_mode->has_state() + ? sl_relay_1_mode->state.c_str() + : "Unknown"); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("standard_hw_relays", " Relay 2: %s", sl_relay_2_mode->has_state() + ? sl_relay_2_mode->state.c_str() + : "Unknown"); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("standard_hw_relays", " Relay 3: %s", sl_relay_3_mode->has_state() + ? sl_relay_3_mode->state.c_str() + : "Unknown"); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("standard_hw_relays", " Relay 4: %s", sl_relay_4_mode->has_state() + ? sl_relay_4_mode->state.c_str() + : "Unknown"); + + // Relay's states + ESP_LOGCONFIG("standard_hw_relays", "Relay%s state%s:", + id(gang_count_plural_suffix).c_str(), + id(gang_count_plural_suffix).c_str()); + ESP_LOGCONFIG("standard_hw_relays", " Relay 1: %s", sw_relay_1->state ? "ON" : "OFF"); + if (id(gang_count) >= 2) + ESP_LOGCONFIG("standard_hw_relays", " Relay 2: %s", sw_relay_2->state ? "ON" : "OFF"); + if (id(gang_count) >= 3) + ESP_LOGCONFIG("standard_hw_relays", " Relay 3: %s", sw_relay_3->state ? "ON" : "OFF"); + if (id(gang_count) >= 4) + ESP_LOGCONFIG("standard_hw_relays", " Relay 4: %s", sw_relay_4->state ? "ON" : "OFF"); + ESP_LOGCONFIG("standard_hw_relays", "Expose Relay's LEDs to Home Assistant: %s", + YESNO(sw_expose_relays_leds_to_ha->state)); + + // Boot initialization statuses + ESP_LOGCONFIG("standard_hw_relays", "Boot initialization flags:"); + ESP_LOGCONFIG("standard_hw_relays", " Overall: %s", YESNO(id(boot_initialization_relays))); + ESP_LOGCONFIG("standard_hw_relays", " Groups: %s", + YESNO(id(boot_initialization_relays_group_assignments))); + ESP_LOGCONFIG("standard_hw_relays", " Light modes: %s", YESNO(id(boot_initialization_relays_light_modes))); + ESP_LOGCONFIG("standard_hw_relays", " Relay modes: %s", YESNO(id(boot_initialization_relays_relay_modes))); + ESP_LOGCONFIG("standard_hw_relays", " Status LEDs: %s", YESNO(id(boot_initialization_relays_relay_leds))); + + // Substitutions + ESP_LOGCONFIG("standard_hw_relays", "Restore modes:"); + ESP_LOGCONFIG("standard_hw_relays", " Relays: ${RELAY_RESTORE_MODE}"); + ESP_LOGCONFIG("standard_hw_relays", " Status LEDs: ${LIGHT_RELAYS_RESTORE_MODE}"); + + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif - // Relay's modes - ESP_LOGCONFIG("core_hw_relays", "Relay%s mode%s:", - id(gang_count_plural_suffix).c_str(), - id(gang_count_plural_suffix).c_str()); - ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sl_relay_1_mode->has_state() - ? sl_relay_1_mode->state.c_str() - : "Unknown"); - if (id(gang_count) >= 2) - ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sl_relay_2_mode->has_state() - ? sl_relay_2_mode->state.c_str() - : "Unknown"); - if (id(gang_count) >= 3) - ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sl_relay_3_mode->has_state() - ? sl_relay_3_mode->state.c_str() - : "Unknown"); - if (id(gang_count) >= 4) - ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sl_relay_4_mode->has_state() - ? sl_relay_4_mode->state.c_str() - : "Unknown"); - - // Relay's states - ESP_LOGCONFIG("core_hw_relays", "Relay%s state%s:", - id(gang_count_plural_suffix).c_str(), - id(gang_count_plural_suffix).c_str()); - ESP_LOGCONFIG("core_hw_relays", " Relay 1: %s", sw_relay_1->state ? "ON" : "OFF"); - if (id(gang_count) >= 2) - ESP_LOGCONFIG("core_hw_relays", " Relay 2: %s", sw_relay_2->state ? "ON" : "OFF"); - if (id(gang_count) >= 3) - ESP_LOGCONFIG("core_hw_relays", " Relay 3: %s", sw_relay_3->state ? "ON" : "OFF"); - if (id(gang_count) >= 4) - ESP_LOGCONFIG("core_hw_relays", " Relay 4: %s", sw_relay_4->state ? "ON" : "OFF"); - ESP_LOGCONFIG("core_hw_relays", "Expose Relay's LEDs to Home Assistant: %s", - YESNO(sw_expose_relays_leds_to_ha->state)); - - // Boot initialization statuses - ESP_LOGCONFIG("core_hw_relays", "Boot initialization flags:"); - ESP_LOGCONFIG("core_hw_relays", " Overall: %s", YESNO(id(boot_initialization_relays))); - ESP_LOGCONFIG("core_hw_relays", " Light modes: %s", YESNO(id(boot_initialization_relays_light_modes))); - ESP_LOGCONFIG("core_hw_relays", " Relay modes: %s", YESNO(id(boot_initialization_relays_relay_modes))); - ESP_LOGCONFIG("core_hw_relays", " Status LEDs: %s", YESNO(id(boot_initialization_relays_relay_leds))); - - // Substitutions - ESP_LOGCONFIG("core_hw_relays", "Restore modes:"); - ESP_LOGCONFIG("core_hw_relays", " Relays: ${RELAY_RESTORE_MODE}"); - ESP_LOGCONFIG("core_hw_relays", " Status LEDs: ${LIGHT_RELAYS_RESTORE_MODE}"); + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Relays"); - id: show_relay_status mode: restart @@ -698,7 +769,7 @@ script: - script.wait: boot_initialize_relays - lambda: |- if (not id(boot_initialization_relays)) { - ESP_LOGW("core_hw_relays", "Relays not initialized yet"); + ESP_LOGW("standard_hw_relays", "Relays not initialized yet"); if (not boot_initialize_relays->is_running()) boot_initialize_relays->execute(); return; @@ -741,8 +812,8 @@ script: break; } - ESP_LOGV("core_hw_relays", "Relay %" PRIu8 " is %s", i + 1, relay_state ? "ON" : "OFF"); - ESP_LOGV("core_hw_relays", "Light Mode for Relay %" PRIu8 ": %s", i + 1, light_mode.c_str()); + ESP_LOGV("standard_hw_relays", "Relay %" PRIu8 " is %s", i + 1, relay_state ? "ON" : "OFF"); + ESP_LOGV("standard_hw_relays", "Light Mode for Relay %" PRIu8 ": %s", i + 1, light_mode.c_str()); // Use light_set_state for light updates if (relay_state) { diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml similarity index 85% rename from ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml index 4587626..bf7205c 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_vibration.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome Core - Hardware - Vibration system ##### +##### Purpose: ESPHome - Standard - Hardware - Vibration system ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### @@ -35,7 +35,7 @@ button: esphome: platformio_options: build_flags: - - -D TX_ULTIMATE_EASY_CORE_HW_VIBRATION + - -D TX_ULTIMATE_EASY_STANDARD_HW_VIBRATION number: - id: nr_vibrating_duration @@ -60,23 +60,30 @@ ota: script: - id: !extend dump_config then: + - lambda: |- + // Configuration + ESP_LOGCONFIG("standard_hw_vibration", "Touch - Vibration feedback: %s", + sl_touch_vibration_feedback->state.c_str()); + ESP_LOGCONFIG("standard_hw_vibration", "Vibrate duration: %.0fms", nr_vibrating_duration->state); + ESP_LOGCONFIG("standard_hw_vibration", "Vibrate max duration: ${vibration_max_duration}"); + + // State + if (bs_vibrating->state) + ESP_LOGW("standard_hw_vibration", "Vibrating now: YES"); + else + ESP_LOGCONFIG("standard_hw_vibration", "Vibrating now: No"); + + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif - // Configuration - ESP_LOGCONFIG("core_hw_vibration", "Touch - Vibration feedback: %s", - sl_touch_vibration_feedback->state.c_str()); - ESP_LOGCONFIG("core_hw_vibration", "Vibrate duration: %.0fms", nr_vibrating_duration->state); - ESP_LOGCONFIG("core_hw_vibration", "Vibrate max duration: ${vibration_max_duration}"); - - // State - if (bs_vibrating->state) - ESP_LOGW("core_hw_vibration", "Vibrating now: YES"); - else - ESP_LOGCONFIG("core_hw_vibration", "Vibrating now: No"); + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Vibration"); - id: !extend touch_on_multi_touch_release then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml similarity index 91% rename from ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml index e416737..800927d 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome - Add-on - Speaker ##### +##### Purpose: ESPHome - Standard - Speaker ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### @@ -17,7 +17,7 @@ substitutions: tone_volume_change: "scale_up:d=32,o=5,b=100:c,c#,d#,e,f#,g#,a#,b" # Use "none" to disable sound packages: - core_hw_audio: !include TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml + standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml api: actions: @@ -31,14 +31,14 @@ api: - lambda: |- rtttl_speaker->stop(); if (speaker_volume->state > 0) { - ESP_LOGI("api", "Play tone: '%s'", tone.c_str()); + ESP_LOGI("standard_speaker", "Play tone: '%s'", tone.c_str()); rtttl_speaker->play(tone.c_str()); } esphome: platformio_options: build_flags: - - -D TX_ULTIMATE_EASY_ADDON_SPEAKER + - -D TX_ULTIMATE_EASY_STANDARD_SPEAKER number: - id: speaker_volume @@ -74,19 +74,20 @@ rtttl: speaker: speaker_embedded script: - - id: !extend dump_config + - id: !extend dump_config_list_packages then: + - script.wait: dump_config - lambda: |- // Check for requirements #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif - #if !defined(TX_ULTIMATE_EASY_CORE_HW_AUDIO) - #error "The package TX-Ultimate-Easy-ESPHome_core_hw_audio.yaml is required." + #if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO) + #error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required." #endif // Identify itself - ESP_LOGCONFIG("addon_speaker", "Add-on Speaker installed"); + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Speaker"); - id: speaker_play_click then: diff --git a/TX-Ultimate-Easy-ESPHome.yaml b/TX-Ultimate-Easy-ESPHome.yaml index 4e1c17d..f8cff7b 100644 --- a/TX-Ultimate-Easy-ESPHome.yaml +++ b/TX-Ultimate-Easy-ESPHome.yaml @@ -19,8 +19,8 @@ packages: ref: latest # Or you can specify a version, like `ref: v2024.12.6` refresh: 5min files: - - ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + - ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages + - ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml # Adds experimental Media Player (limited) - # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_speaker.yaml # Adds basic audio speaker support ... From c73cb950eb7864dd2f7fb4140b70fc11ec958dca Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:48:04 +0100 Subject: [PATCH 036/109] lint --- .github/workflows/validate_esphome.yml | 121 ++++++++++++++++++-- .github/workflows/validate_esphome_beta.yml | 4 +- 2 files changed, 112 insertions(+), 13 deletions(-) diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index 2388c43..b62e16b 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -27,36 +27,135 @@ jobs: - name: Validate YAML files run: find . -name "*.yaml" -exec yamllint -c ./.rules/yamllint.yml {} + - build_basic: - name: Basic + build_ard_core: + name: Core (Arduino) + needs: code_scan runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Core (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_core.yaml" + version: latest + + build_idf_core: + name: Core (IDF) + needs: code_scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Core (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_core.yaml" + version: latest + + build_idf53_core: + name: Core (IDFv5.3) + needs: code_scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Core (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_core.yaml" + version: latest + + build_ard_basic: + name: Basic (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Basic (Arduino) uses: esphome/build-action@main with: yaml-file: ".test/esphome_ard_basic.yaml" version: latest - build_bluetooth_proxy_4: - name: Bluetooth Proxy (IDF) + build_idf_basic: + name: Core (IDF) + needs: build_idf_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Basic (IDF) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf_basic.yaml" version: latest - build_bluetooth_proxy_53: - name: Bluetooth Proxy (IDF v5.3) + build_idf53_basic: + name: Basic (IDFv5.3) + needs: build_idf53_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build core + - name: Build Basic (IDFv5.3) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf53_bluetooth_proxy.yaml" + yaml-file: ".test/esphome_idf53_basic.yaml" + version: latest + + build_ard_ble_proxy: + name: Bluetooth Proxy (Ard) + needs: build_ard_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (Ard) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_ble_proxy.yaml" + version: latest + + build_idf_ble_proxy: + name: Bluetooth Proxy (IDF) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_ble_proxy.yaml" + version: latest + + build_idf53_ble_proxy: + name: Bluetooth Proxy (IDFv5.3) + needs: build_idf53_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build BLE Proxy (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_ble_proxy.yaml" + version: latest + + build_idf_media_player: + name: Media Player (IDF) + needs: build_idf_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Media Player (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_media_player.yaml" + version: latest + + build_idf53_media_player: + name: Media Player (IDFv5.3) + needs: build_idf53_basic + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build Media Player (IDFv5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_media_player.yaml" version: latest ... diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 6367c31..b23d039 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -147,7 +147,7 @@ jobs: build_idf53_ble_proxy: name: Bluetooth Proxy (IDFv5.3) - needs: build_idf_basic + needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main @@ -171,7 +171,7 @@ jobs: build_idf53_media_player: name: Media Player (IDFv5.3) - needs: build_idf_basic + needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main From ea12c1d42264bf1967e33e7c7d2e4fb8cc5d01e1 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:48:58 +0100 Subject: [PATCH 037/109] Lint --- ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml index 800927d..1302652 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml @@ -62,8 +62,8 @@ number: volume: !lambda return x/100.0f; - if: condition: - - lambda: 'return x > 0;' - - lambda: 'return "${tone_volume_change}" != "none";' + - lambda: return x > 0; + - lambda: return "${tone_volume_change}" != "none"; then: - rtttl.play: id: rtttl_speaker From 7d12ddb0e5c405009bb64ab7c597529f822f3860 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 01:56:39 +0100 Subject: [PATCH 038/109] Add WiFi SSID --- .test/esphome_ard_basic.yaml | 4 ++++ .test/esphome_ard_ble_proxy.yaml | 4 ++++ .test/esphome_ard_core.yaml | 4 ++++ .test/esphome_idf53_basic.yaml | 4 ++++ .test/esphome_idf53_ble_proxy.yaml | 4 ++++ .test/esphome_idf53_core.yaml | 4 ++++ .test/esphome_idf53_media_player.yaml | 4 ++++ .test/esphome_idf_basic.yaml | 4 ++++ .test/esphome_idf_ble_proxy.yaml | 4 ++++ .test/esphome_idf_core.yaml | 4 ++++ .test/esphome_idf_media_player.yaml | 4 ++++ 11 files changed, 44 insertions(+) diff --git a/.test/esphome_ard_basic.yaml b/.test/esphome_ard_basic.yaml index 91753ec..20554a4 100644 --- a/.test/esphome_ard_basic.yaml +++ b/.test/esphome_ard_basic.yaml @@ -6,4 +6,8 @@ packages: esp32: framework: type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_ard_ble_proxy.yaml b/.test/esphome_ard_ble_proxy.yaml index e21e328..86cc07c 100644 --- a/.test/esphome_ard_ble_proxy.yaml +++ b/.test/esphome_ard_ble_proxy.yaml @@ -7,4 +7,8 @@ packages: esp32: framework: type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_ard_core.yaml b/.test/esphome_ard_core.yaml index bee25b3..1b50c90 100644 --- a/.test/esphome_ard_core.yaml +++ b/.test/esphome_ard_core.yaml @@ -5,4 +5,8 @@ packages: esp32: framework: type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf53_basic.yaml b/.test/esphome_idf53_basic.yaml index 44ebb3b..1dabf1f 100644 --- a/.test/esphome_idf53_basic.yaml +++ b/.test/esphome_idf53_basic.yaml @@ -8,4 +8,8 @@ esp32: type: esp-idf version: 5.3.1 platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf53_ble_proxy.yaml b/.test/esphome_idf53_ble_proxy.yaml index d4aa126..b17b6d2 100644 --- a/.test/esphome_idf53_ble_proxy.yaml +++ b/.test/esphome_idf53_ble_proxy.yaml @@ -9,4 +9,8 @@ esp32: type: esp-idf version: 5.3.1 platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf53_core.yaml b/.test/esphome_idf53_core.yaml index 438146c..18239c7 100644 --- a/.test/esphome_idf53_core.yaml +++ b/.test/esphome_idf53_core.yaml @@ -7,4 +7,8 @@ esp32: type: esp-idf version: 5.3.1 platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf53_media_player.yaml b/.test/esphome_idf53_media_player.yaml index c8c4414..fdc7e14 100644 --- a/.test/esphome_idf53_media_player.yaml +++ b/.test/esphome_idf53_media_player.yaml @@ -9,4 +9,8 @@ esp32: type: esp-idf version: 5.3.1 platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf_basic.yaml b/.test/esphome_idf_basic.yaml index 9f20465..ab3d202 100644 --- a/.test/esphome_idf_basic.yaml +++ b/.test/esphome_idf_basic.yaml @@ -6,4 +6,8 @@ packages: esp32: framework: type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf_ble_proxy.yaml b/.test/esphome_idf_ble_proxy.yaml index 3aeba92..c972d0f 100644 --- a/.test/esphome_idf_ble_proxy.yaml +++ b/.test/esphome_idf_ble_proxy.yaml @@ -7,4 +7,8 @@ packages: esp32: framework: type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf_core.yaml b/.test/esphome_idf_core.yaml index 3daf403..846889a 100644 --- a/.test/esphome_idf_core.yaml +++ b/.test/esphome_idf_core.yaml @@ -5,4 +5,8 @@ packages: esp32: framework: type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... diff --git a/.test/esphome_idf_media_player.yaml b/.test/esphome_idf_media_player.yaml index 1c2697b..7f94d6e 100644 --- a/.test/esphome_idf_media_player.yaml +++ b/.test/esphome_idf_media_player.yaml @@ -7,4 +7,8 @@ packages: esp32: framework: type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password ... From 3d21c2ebcb8e8efed293fc004325295540dd08a4 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:02:01 +0100 Subject: [PATCH 039/109] Add cinttypes --- components/tx_ultimate_easy/tx_ultimate_easy.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/tx_ultimate_easy/tx_ultimate_easy.cpp b/components/tx_ultimate_easy/tx_ultimate_easy.cpp index 640f3db..d3de82b 100644 --- a/components/tx_ultimate_easy/tx_ultimate_easy.cpp +++ b/components/tx_ultimate_easy/tx_ultimate_easy.cpp @@ -2,6 +2,7 @@ #include "esphome/core/log.h" #include "tx_ultimate_easy.h" +#include #include namespace esphome { From 6221e109e8b33a0f08068c10d3f5fa6db8a5a922 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:08:11 +0100 Subject: [PATCH 040/109] Rename speaker file --- ...r.yaml => TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename ESPHome/{TX-Ultimate-Easy-ESPHome_standard_speaker.yaml => TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml} (98%) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml similarity index 98% rename from ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml rename to ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml index 1302652..3492af8 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml @@ -87,7 +87,7 @@ script: #endif // Identify itself - ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Speaker"); + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard - Hardware - Speaker"); - id: speaker_play_click then: From 9828b6ff8a8b8110cb833a35724eb69b923a90e7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:15:51 +0100 Subject: [PATCH 041/109] Add tests core+hw_relays --- .github/workflows/validate_esphome_beta.yml | 54 +++++++++++++++++---- .test/esphome_ard_hw_relays.yaml | 13 +++++ .test/esphome_idf53_hw_relays.yaml | 15 ++++++ .test/esphome_idf_hw_relays.yaml | 13 +++++ 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 .test/esphome_ard_hw_relays.yaml create mode 100644 .test/esphome_idf53_hw_relays.yaml create mode 100644 .test/esphome_idf_hw_relays.yaml diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index b23d039..777b427 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -74,12 +74,12 @@ jobs: version: beta build_idf53_core: - name: Core (IDFv5.3) + name: Core (IDF v5.3) needs: code_scan runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Core (IDFv5.3) + - name: Build Core (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_core.yaml" @@ -98,7 +98,7 @@ jobs: version: beta build_idf_basic: - name: Core (IDF) + name: Basic (IDF) needs: build_idf_core runs-on: ubuntu-latest steps: @@ -110,17 +110,53 @@ jobs: version: beta build_idf53_basic: - name: Basic (IDFv5.3) + name: Basic (IDF v5.3) needs: build_idf53_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Basic (IDFv5.3) + - name: Build Basic (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_basic.yaml" version: beta + build_ard_hw_relays: + name: HW Relays (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_relays.yaml" + version: beta + + build_idf_hw_relays: + name: HW Relays (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_relays.yaml" + version: beta + + build_idf53_hw_relays: + name: HW Relays (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_relays.yaml" + version: beta + build_ard_ble_proxy: name: Bluetooth Proxy (Ard) needs: build_ard_basic @@ -146,12 +182,12 @@ jobs: version: beta build_idf53_ble_proxy: - name: Bluetooth Proxy (IDFv5.3) + name: Bluetooth Proxy (IDF v5.3) needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build BLE Proxy (IDFv5.3) + - name: Build BLE Proxy (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_ble_proxy.yaml" @@ -170,12 +206,12 @@ jobs: version: beta build_idf53_media_player: - name: Media Player (IDFv5.3) + name: Media Player (IDF v5.3) needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Media Player (IDFv5.3) + - name: Build Media Player (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_media_player.yaml" diff --git a/.test/esphome_ard_hw_relays.yaml b/.test/esphome_ard_hw_relays.yaml new file mode 100644 index 0000000..704ac7d --- /dev/null +++ b/.test/esphome_ard_hw_relays.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + +esp32: + framework: + type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf53_hw_relays.yaml b/.test/esphome_idf53_hw_relays.yaml new file mode 100644 index 0000000..d9f5bd0 --- /dev/null +++ b/.test/esphome_idf53_hw_relays.yaml @@ -0,0 +1,15 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf_hw_relays.yaml b/.test/esphome_idf_hw_relays.yaml new file mode 100644 index 0000000..d78b1b4 --- /dev/null +++ b/.test/esphome_idf_hw_relays.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + +esp32: + framework: + type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... From 0c9a5ac65e79bc569d7baa975626ae6908fe3490 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:19:59 +0100 Subject: [PATCH 042/109] Rebuild tone_volume_change play on volume change IDF v5.3 compatibility --- ...X-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml index 3492af8..a457d99 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml @@ -60,14 +60,11 @@ number: - speaker.volume_set: id: speaker_embedded volume: !lambda return x/100.0f; - - if: - condition: - - lambda: return x > 0; - - lambda: return "${tone_volume_change}" != "none"; - then: - - rtttl.play: - id: rtttl_speaker - rtttl: "${tone_volume_change}" + - lambda: |- + static const std::string tone_volume_change = "${tone_volume_change}"; + // Play sound if tone_volume_change is not "none" + if (x > 0 and !tone_volume_change.empty() and tone_volume_change != "none") + rtttl_speaker->play(tone_volume_change); rtttl: - id: rtttl_speaker From 2811eedffb18867d36141d234f18405ed9465a80 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:23:24 +0100 Subject: [PATCH 043/109] Bump version --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 035e90a..9ec75a4 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.19 +2024.12.21 \ No newline at end of file diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 5803b9d..f338ed0 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.19 +version: 2024.12.21 \ No newline at end of file From fa516a66cc7d5c488ecfe3b72309a38ee6f41bf4 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:27:48 +0100 Subject: [PATCH 044/109] Add HW Speaker tests --- .github/workflows/validate_esphome_beta.yml | 36 +++++++++++++++++++++ .test/esphome_ard_hw_speaker.yaml | 13 ++++++++ .test/esphome_idf53_hw_speaker.yaml | 15 +++++++++ .test/esphome_idf_hw_speaker.yaml | 13 ++++++++ 4 files changed, 77 insertions(+) create mode 100644 .test/esphome_ard_hw_speaker.yaml create mode 100644 .test/esphome_idf53_hw_speaker.yaml create mode 100644 .test/esphome_idf_hw_speaker.yaml diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 777b427..e25e096 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -157,6 +157,42 @@ jobs: yaml-file: ".test/esphome_idf53_hw_relays.yaml" version: beta + build_ard_hw_speaker: + name: HW Speaker (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_speaker.yaml" + version: beta + + build_idf_hw_speaker: + name: HW Speaker (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_speaker.yaml" + version: beta + + build_idf53_hw_speaker: + name: HW Speaker (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_speaker.yaml" + version: beta + build_ard_ble_proxy: name: Bluetooth Proxy (Ard) needs: build_ard_basic diff --git a/.test/esphome_ard_hw_speaker.yaml b/.test/esphome_ard_hw_speaker.yaml new file mode 100644 index 0000000..62272ca --- /dev/null +++ b/.test/esphome_ard_hw_speaker.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml + +esp32: + framework: + type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf53_hw_speaker.yaml b/.test/esphome_idf53_hw_speaker.yaml new file mode 100644 index 0000000..651ac37 --- /dev/null +++ b/.test/esphome_idf53_hw_speaker.yaml @@ -0,0 +1,15 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf_hw_speaker.yaml b/.test/esphome_idf_hw_speaker.yaml new file mode 100644 index 0000000..8bcf3ff --- /dev/null +++ b/.test/esphome_idf_hw_speaker.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml + +esp32: + framework: + type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... From 9d0fcf6bfa7458d352c3d11ad7a237d05ed08e0a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:30:52 +0100 Subject: [PATCH 045/109] Test Media Player with Arduino --- .github/workflows/validate_esphome_beta.yml | 10 +++++----- ...player.yaml => esphome_ard_media_player.yaml} | 2 +- .test/esphome_idf53_media_player.yaml | 16 ---------------- 3 files changed, 6 insertions(+), 22 deletions(-) rename .test/{esphome_idf_media_player.yaml => esphome_ard_media_player.yaml} (95%) delete mode 100644 .test/esphome_idf53_media_player.yaml diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index e25e096..43f2859 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -229,16 +229,16 @@ jobs: yaml-file: ".test/esphome_idf53_ble_proxy.yaml" version: beta - build_idf_media_player: - name: Media Player (IDF) - needs: build_idf_basic + build_ard_media_player: + name: Media Player (Ard) + needs: build_ard_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Media Player (IDF) + - name: Build Media Player (Ard) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf_media_player.yaml" + yaml-file: ".test/esphome_ard_media_player.yaml" version: beta build_idf53_media_player: diff --git a/.test/esphome_idf_media_player.yaml b/.test/esphome_ard_media_player.yaml similarity index 95% rename from .test/esphome_idf_media_player.yaml rename to .test/esphome_ard_media_player.yaml index 7f94d6e..9c1dc40 100644 --- a/.test/esphome_idf_media_player.yaml +++ b/.test/esphome_ard_media_player.yaml @@ -6,7 +6,7 @@ packages: esp32: framework: - type: esp-idf + type: arduino wifi: ssid: !secret wifi_ssid diff --git a/.test/esphome_idf53_media_player.yaml b/.test/esphome_idf53_media_player.yaml deleted file mode 100644 index fdc7e14..0000000 --- a/.test/esphome_idf53_media_player.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -packages: - core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml - addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password -... From b69bc6916b5cd86eef90639288bf2dd4e016888f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:33:52 +0100 Subject: [PATCH 046/109] Comments only --- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml index a457d99..e9d5c3b 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml @@ -2,7 +2,7 @@ ##### TX Ultimate Easy for ESPHome ##### ##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### #################################################################################################### -##### Purpose: ESPHome - Standard - Speaker ##### +##### Purpose: ESPHome - Standard - Hardware - Speaker ##### #################################################################################################### ##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### #################################################################################################### From f154a483cc553f0c04efae85d834d38386bcee64 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:36:47 +0100 Subject: [PATCH 047/109] Run tests when test script changes --- .github/workflows/validate_esphome_beta.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 43f2859..edf453f 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -4,22 +4,26 @@ name: Validate ESPHome (Beta) on: # yamllint disable-line rule:truthy push: paths: - - "*.yaml" - - "ESPHome/*.yaml" - - ".test/*.yaml" - - "*.h" - "*.c" - "*.cpp" + - "*.h" - "*.py" + - "*.yaml" + - ".github/workflows/*.*" + - ".test/*.*" + - "components/*.*" + - "components/tx_ultimate_easy/*.*" + - "ESPHome/*.*" branches: - main pull_request: paths: - - "*.yaml" - - "*.h" - "*.c" - "*.cpp" + - "*.h" - "*.py" + - "*.yaml" + - ".github/workflows/*.*" - ".test/*.*" - "components/*.*" - "components/tx_ultimate_easy/*.*" From 3401aaf4a3155855c909303bd0d8d98fe27cb35b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:42:36 +0100 Subject: [PATCH 048/109] Add tests with hw_vibration --- .github/workflows/validate_esphome.yml | 136 ++++++++++++++++++-- .github/workflows/validate_esphome_beta.yml | 36 ++++++ .test/esphome_ard_hw_vibration.yaml | 13 ++ .test/esphome_idf53_hw_vibration.yaml | 15 +++ .test/esphome_idf_hw_vibration.yaml | 13 ++ 5 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 .test/esphome_ard_hw_vibration.yaml create mode 100644 .test/esphome_idf53_hw_vibration.yaml create mode 100644 .test/esphome_idf_hw_vibration.yaml diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index b62e16b..cdcfed9 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -52,12 +52,12 @@ jobs: version: latest build_idf53_core: - name: Core (IDFv5.3) + name: Core (IDF v5.3) needs: code_scan runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Core (IDFv5.3) + - name: Build Core (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_core.yaml" @@ -76,7 +76,7 @@ jobs: version: latest build_idf_basic: - name: Core (IDF) + name: Basic (IDF) needs: build_idf_core runs-on: ubuntu-latest steps: @@ -88,17 +88,125 @@ jobs: version: latest build_idf53_basic: - name: Basic (IDFv5.3) + name: Basic (IDF v5.3) needs: build_idf53_core runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Basic (IDFv5.3) + - name: Build Basic (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_basic.yaml" version: latest + build_ard_hw_relays: + name: HW Relays (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_relays.yaml" + version: latest + + build_idf_hw_relays: + name: HW Relays (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_relays.yaml" + version: latest + + build_idf53_hw_relays: + name: HW Relays (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Relays (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_relays.yaml" + version: latest + + build_ard_hw_speaker: + name: HW Speaker (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_speaker.yaml" + version: latest + + build_idf_hw_speaker: + name: HW Speaker (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_speaker.yaml" + version: latest + + build_idf53_hw_speaker: + name: HW Speaker (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Speaker (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_speaker.yaml" + version: latest + + build_ard_hw_vibration: + name: HW Vibration (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_vibration.yaml" + version: latest + + build_idf_hw_vibration: + name: HW Vibration (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_vibration.yaml" + version: latest + + build_idf53_hw_vibration: + name: HW Vibration (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_vibration.yaml" + version: latest + build_ard_ble_proxy: name: Bluetooth Proxy (Ard) needs: build_ard_basic @@ -124,36 +232,36 @@ jobs: version: latest build_idf53_ble_proxy: - name: Bluetooth Proxy (IDFv5.3) + name: Bluetooth Proxy (IDF v5.3) needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build BLE Proxy (IDFv5.3) + - name: Build BLE Proxy (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_ble_proxy.yaml" version: latest - build_idf_media_player: - name: Media Player (IDF) - needs: build_idf_basic + build_ard_media_player: + name: Media Player (Ard) + needs: build_ard_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Media Player (IDF) + - name: Build Media Player (Ard) uses: esphome/build-action@main with: - yaml-file: ".test/esphome_idf_media_player.yaml" + yaml-file: ".test/esphome_ard_media_player.yaml" version: latest build_idf53_media_player: - name: Media Player (IDFv5.3) + name: Media Player (IDF v5.3) needs: build_idf53_basic runs-on: ubuntu-latest steps: - uses: actions/checkout@main - - name: Build Media Player (IDFv5.3) + - name: Build Media Player (IDF v5.3) uses: esphome/build-action@main with: yaml-file: ".test/esphome_idf53_media_player.yaml" diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index edf453f..bd03601 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -197,6 +197,42 @@ jobs: yaml-file: ".test/esphome_idf53_hw_speaker.yaml" version: beta + build_ard_hw_vibration: + name: HW Vibration (Arduino) + needs: build_ard_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (Arduino) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_ard_hw_vibration.yaml" + version: beta + + build_idf_hw_vibration: + name: HW Vibration (IDF) + needs: build_idf_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (IDF) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf_hw_vibration.yaml" + version: beta + + build_idf53_hw_vibration: + name: HW Vibration (IDF v5.3) + needs: build_idf53_core + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: Build HW Vibration (IDF v5.3) + uses: esphome/build-action@main + with: + yaml-file: ".test/esphome_idf53_hw_vibration.yaml" + version: beta + build_ard_ble_proxy: name: Bluetooth Proxy (Ard) needs: build_ard_basic diff --git a/.test/esphome_ard_hw_vibration.yaml b/.test/esphome_ard_hw_vibration.yaml new file mode 100644 index 0000000..5dbacea --- /dev/null +++ b/.test/esphome_ard_hw_vibration.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + +esp32: + framework: + type: arduino + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf53_hw_vibration.yaml b/.test/esphome_idf53_hw_vibration.yaml new file mode 100644 index 0000000..d0a5ed3 --- /dev/null +++ b/.test/esphome_idf53_hw_vibration.yaml @@ -0,0 +1,15 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/esphome_idf_hw_vibration.yaml b/.test/esphome_idf_hw_vibration.yaml new file mode 100644 index 0000000..8ac9039 --- /dev/null +++ b/.test/esphome_idf_hw_vibration.yaml @@ -0,0 +1,13 @@ +--- +packages: + core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml + standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + +esp32: + framework: + type: esp-idf + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... From 02c7c1aff1031339217bc255cd36066bcdfe2ee2 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:47:00 +0100 Subject: [PATCH 049/109] Remove media player test with idf 5.3 --- .github/workflows/validate_esphome.yml | 12 ------------ .github/workflows/validate_esphome_beta.yml | 12 ------------ 2 files changed, 24 deletions(-) diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index cdcfed9..114fe38 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -254,16 +254,4 @@ jobs: with: yaml-file: ".test/esphome_ard_media_player.yaml" version: latest - - build_idf53_media_player: - name: Media Player (IDF v5.3) - needs: build_idf53_basic - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - name: Build Media Player (IDF v5.3) - uses: esphome/build-action@main - with: - yaml-file: ".test/esphome_idf53_media_player.yaml" - version: latest ... diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index bd03601..6ed9cfd 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -280,16 +280,4 @@ jobs: with: yaml-file: ".test/esphome_ard_media_player.yaml" version: beta - - build_idf53_media_player: - name: Media Player (IDF v5.3) - needs: build_idf53_basic - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - name: Build Media Player (IDF v5.3) - uses: esphome/build-action@main - with: - yaml-file: ".test/esphome_idf53_media_player.yaml" - version: beta ... From 088213137f228670c80acd8332e1967c90430e80 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 02:55:27 +0100 Subject: [PATCH 050/109] Do not try media player and speaker together --- .github/workflows/validate_esphome.yml | 5 ++++- .github/workflows/validate_esphome_beta.yml | 5 ++++- .test/esphome_ard_media_player.yaml | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index 114fe38..70cca04 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -245,7 +245,10 @@ jobs: build_ard_media_player: name: Media Player (Ard) - needs: build_ard_basic + needs: + - build_ard_basic + - build_ard_hw_relays + - build_ard_hw_vibration runs-on: ubuntu-latest steps: - uses: actions/checkout@main diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 6ed9cfd..fa0c57d 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -271,7 +271,10 @@ jobs: build_ard_media_player: name: Media Player (Ard) - needs: build_ard_basic + needs: + - build_ard_basic + - build_ard_hw_relays + - build_ard_hw_vibration runs-on: ubuntu-latest steps: - uses: actions/checkout@main diff --git a/.test/esphome_ard_media_player.yaml b/.test/esphome_ard_media_player.yaml index 9c1dc40..9a9f744 100644 --- a/.test/esphome_ard_media_player.yaml +++ b/.test/esphome_ard_media_player.yaml @@ -1,7 +1,8 @@ --- packages: core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml esp32: From fee446c5e268f83dc48bb7119bd4d049b5e3d2ce Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 03:12:29 +0100 Subject: [PATCH 051/109] Specify permissions and trigger's files types --- .github/workflows/validate_esphome.yml | 4 +++ .github/workflows/validate_esphome_beta.yml | 36 +++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/validate_esphome.yml b/.github/workflows/validate_esphome.yml index 70cca04..a516df5 100644 --- a/.github/workflows/validate_esphome.yml +++ b/.github/workflows/validate_esphome.yml @@ -1,6 +1,10 @@ --- name: Validate ESPHome (Latest) +permissions: + contents: read + pull-requests: read + on: # yamllint disable-line rule:truthy workflow_dispatch: diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index fa0c57d..9cd663d 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -1,33 +1,29 @@ --- name: Validate ESPHome (Beta) +permissions: + contents: read + pull-requests: read + on: # yamllint disable-line rule:truthy push: paths: - - "*.c" - - "*.cpp" - - "*.h" - - "*.py" - - "*.yaml" - - ".github/workflows/*.*" - - ".test/*.*" - - "components/*.*" - - "components/tx_ultimate_easy/*.*" - - "ESPHome/*.*" + - "*.{yml,yaml,h,cpp,c,py}" + - ".github/workflows/*.{yml,yaml,h,cpp,c,py}" + - ".test/*.{yml,yaml,h,cpp,c,py}" + - "components/*.{yml,yaml,h,cpp,c,py}" + - "components/tx_ultimate_easy/*.{yml,yaml,h,cpp,c,py}" + - "ESPHome/*.{yml,yaml,h,cpp,c,py}" branches: - main pull_request: paths: - - "*.c" - - "*.cpp" - - "*.h" - - "*.py" - - "*.yaml" - - ".github/workflows/*.*" - - ".test/*.*" - - "components/*.*" - - "components/tx_ultimate_easy/*.*" - - "ESPHome/*.*" + - "*.{yml,yaml,h,cpp,c,py}" + - ".github/workflows/*.{yml,yaml,h,cpp,c,py}" + - ".test/*.{yml,yaml,h,cpp,c,py}" + - "components/*.{yml,yaml,h,cpp,c,py}" + - "components/tx_ultimate_easy/*.{yml,yaml,h,cpp,c,py}" + - "ESPHome/*.{yml,yaml,h,cpp,c,py}" workflow_dispatch: concurrency: From 9fad193892d1527dc09fc72ec006ad5c67bbc670 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 27 Dec 2024 02:32:14 +0000 Subject: [PATCH 052/109] Bump version to 2024.12.22 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index cda1ac9..2bc2063 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.21 +2024.12.22 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index ab056b2..3fc2d7e 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.21 +version: 2024.12.22 From b431041b15b21f1a6386d55bd6c18a658b029caf Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 03:37:09 +0100 Subject: [PATCH 053/109] Set relays lights to not be disabled when exposed Resolves #75 --- ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml index 432994f..bb738ad 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml @@ -132,7 +132,7 @@ light: name: Light - Relay 1 of 1 (bottom) platform: partition internal: true - disabled_by_default: true + disabled_by_default: false default_transition_length: ${default_transition_length} restore_mode: ${LIGHT_RELAYS_RESTORE_MODE} segments: From c50bd5ca16ac03bcede5f266fdeb848b0ba5d99f Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 27 Dec 2024 02:40:01 +0000 Subject: [PATCH 054/109] Bump version to 2024.12.23 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 2bc2063..a5ee8d9 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.22 +2024.12.23 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 3fc2d7e..c54bbe0 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.22 +version: 2024.12.23 From 5255912fcf7c99b520418d390e40578114274c3c Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 03:49:39 +0100 Subject: [PATCH 055/109] Match any file with the extensions in any directory --- .github/workflows/validate_esphome_beta.yml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 9cd663d..bd40471 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -8,22 +8,10 @@ permissions: on: # yamllint disable-line rule:truthy push: paths: - - "*.{yml,yaml,h,cpp,c,py}" - - ".github/workflows/*.{yml,yaml,h,cpp,c,py}" - - ".test/*.{yml,yaml,h,cpp,c,py}" - - "components/*.{yml,yaml,h,cpp,c,py}" - - "components/tx_ultimate_easy/*.{yml,yaml,h,cpp,c,py}" - - "ESPHome/*.{yml,yaml,h,cpp,c,py}" - branches: - - main + - "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory pull_request: paths: - - "*.{yml,yaml,h,cpp,c,py}" - - ".github/workflows/*.{yml,yaml,h,cpp,c,py}" - - ".test/*.{yml,yaml,h,cpp,c,py}" - - "components/*.{yml,yaml,h,cpp,c,py}" - - "components/tx_ultimate_easy/*.{yml,yaml,h,cpp,c,py}" - - "ESPHome/*.{yml,yaml,h,cpp,c,py}" + - "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory workflow_dispatch: concurrency: From 4b1aed33ef32298c473a723bef1dbbff19274815 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 27 Dec 2024 02:53:35 +0000 Subject: [PATCH 056/109] Bump version to 2024.12.24 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index a5ee8d9..a1f6a22 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.23 +2024.12.24 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index c54bbe0..e41145d 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.23 +version: 2024.12.24 From d3d5c21d38b4c57735dc21dd7e89a4bf5cbbbd40 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 09:27:13 +0100 Subject: [PATCH 057/109] Add install instructions --- README.md | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b6b6b29..9c9f1c6 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,103 @@ Before getting started, ensure you have: ## Installation -Detailed installation instructions coming soon. The process will include: +Follow these steps to get your TX Ultimate device up and running with ESPHome. -1. Initial ESPHome setup -2. Device flashing -3. Home Assistant integration -4. Basic configuration +### 1. ESPHome Integration Setup + +1. Install ESPHome add-on in Home Assistant if not already installed: + - Go to Settings → Add-ons → Add-on Store + - Search for "ESPHome" + - Click Install +2. Start the ESPHome add-on and verify it's running +3. Access ESPHome dashboard through Home Assistant + +### 2. Device Configuration + +1. In ESPHome dashboard, click "+ New Device" +2. Name your device (e.g., "tx-ultimate-living-room") +3. Select ESP32 as your device type +4. Copy this basic configuration to your new device: + ```yaml + substitutions: + name: tx-ultimate-easy # Change this to your device name + friendly_name: TX Ultimate Easy + + packages: + remote_package: + url: https://github.com/edwardtfn/TX-Ultimate-Easy + ref: main # For latest stable release + # ref: dev # For testing new features + files: + - ESPHome/TX-Ultimate-Easy-ESPHome.yaml + + wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + ``` +5. Click "Save" and then "Install" + +### 3. Device Flashing + +Initial flashing must be done via serial connection. +We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experience. + +#### Required Hardware +- USB-to-UART adapter (3.3V) +- Small Phillips screwdriver +- 5 wires for connections (including one for BOOT to GND) + +#### Flashing Process +1. Open your TX Ultimate device carefully +2. Locate the programming header pins +3. Connect your USB-to-UART adapter: + - GND → GND + - 3.3V → 3.3V + - TX → RX + - RX → TX +4. Put device in flash mode: + - Connect the BOOT pin to GND using a jumper wire + - Power up the device (keeping BOOT connected to GND) + - Remove the BOOT to GND connection +5. Visit [ESPHome Web](https://web.esphome.io) +6. Connect to your device and flash the firmware +7. After successful flash, device will restart and be ready for OTA updates + +#### Detailed Visual Guides +For step-by-step visual instructions, you can reference these existing guides: +- 🇬🇧 [WirelessThings Guide](https://wirelessthings.net/how-to-flash-sonoff-tx-ultimate-with-esphome) - + English guide with detailed photos +- 🇪🇸 [Un loco y su tecnología](https://youtu.be/58v8oqSQgXQ?t=143) - Spanish video tutorial +- 🇩🇪 [SmartHome yourself](https://youtu.be/naDLhX89enQ?t=465) - German video tutorial + +Note: While these guides may use different firmware, the physical flashing process remains the same. + +#### Subsequent Updates +After initial flashing, all future updates can be done wirelessly (OTA) +through the ESPHome dashboard in your ESPHome add-on. + +### 4. Home Assistant Integration + +After successful flashing: +1. Device will automatically be discovered by Home Assistant +2. Accept the discovery notification to add device +3. Device will appear in your Home Assistant Devices dashboard + +### 5. Initial Configuration + +1. In Home Assistant, navigate to: + - Settings → Devices & Services → ESPHome + - Click on your device to access its configuration page +2. Set basic device parameters: + - Model format (EU/US) + - Number of gangs (1-4) + - Relay modes (switch/light) + - Button actions +3. Optional: Configure advanced features + - LED behaviors + - Touch sensitivity + - Haptic feedback + - Audio feedback ## Usage @@ -156,7 +247,8 @@ This project builds upon the work of several amazing projects and contributors: - [SmartHome yourself - SONOFF TX Ultimate for ESPHome](https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome) - [Un loco y su tecnología - Sonoff TX Ultimate with ESPHome](https://www.youtube.com/watch?v=58v8oqSQgXQ) -- @PxPert - [Sonoff TX Ultimate and Voice Assistant](https://community.home-assistant.io/t/sonoff-tx-ultimate-and-voice-assistant/682214?u=edwardtfn) +- [@PxPert](https://github.com/PxPert) - + [Sonoff TX Ultimate and Voice Assistant](https://community.home-assistant.io/t/sonoff-tx-ultimate-and-voice-assistant/682214?u=edwardtfn) Special thanks to all contributors and community members who help make this project better. From 40f8165d5c814c11ef50c76b3464e0b1ba71ba5f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 09:30:55 +0100 Subject: [PATCH 058/109] Fix link to reference in English --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9c9f1c6..a6dd557 100644 --- a/README.md +++ b/README.md @@ -155,11 +155,12 @@ We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experi 7. After successful flash, device will restart and be ready for OTA updates #### Detailed Visual Guides + For step-by-step visual instructions, you can reference these existing guides: -- 🇬🇧 [WirelessThings Guide](https://wirelessthings.net/how-to-flash-sonoff-tx-ultimate-with-esphome) - - English guide with detailed photos +- 🇬🇧 [WirelessThings Guide](https://wirelessthings.io/index.php/2023/12/19/how-to-flash-sonoff-tx-ultimate-with-esphome/) - English guide with detailed photos - 🇪🇸 [Un loco y su tecnología](https://youtu.be/58v8oqSQgXQ?t=143) - Spanish video tutorial - 🇩🇪 [SmartHome yourself](https://youtu.be/naDLhX89enQ?t=465) - German video tutorial + Note: While these guides may use different firmware, the physical flashing process remains the same. From 4266a7cdd8e34e4068311aabab796e0f0eb7be1b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 09:48:52 +0100 Subject: [PATCH 059/109] Add a bit more of details As suggested by CodeRabbitAI --- README.md | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a6dd557..120bce4 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,6 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. remote_package: url: https://github.com/edwardtfn/TX-Ultimate-Easy ref: main # For latest stable release - # ref: dev # For testing new features files: - ESPHome/TX-Ultimate-Easy-ESPHome.yaml @@ -126,6 +125,11 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ssid: !secret wifi_ssid password: !secret wifi_password ``` + + You can also use a specific version tag for better control over updates: + ```yaml + ref: v2025.1.3 # Replace with desired version (format: vYYYY.MM.nn) + ``` 5. Click "Save" and then "Install" ### 3. Device Flashing @@ -171,9 +175,24 @@ through the ESPHome dashboard in your ESPHome add-on. ### 4. Home Assistant Integration After successful flashing: -1. Device will automatically be discovered by Home Assistant -2. Accept the discovery notification to add device -3. Device will appear in your Home Assistant Devices dashboard +1. Ensure your device and Home Assistant are on the same network +2. Device should be automatically discovered within a couple of minutes +3. Accept the discovery notification to add device +4. Device will appear in your Home Assistant Devices dashboard + +#### Troubleshooting Integration +If the device isn't discovered automatically: +1. Verify your device is powered and connected to your network: + - Look for the device in your router's client list + - Consider using [manual IP](https://esphome.io/components/wifi.html#manual-ips) in your device +2. If you missed the discovery notification: + - Go to Settings → Devices & Services + - Click "Add Integration" + - Search for "ESPHome" and enter your device's IP address +3. Still having issues? + - Check your network allows mDNS/discovery traffic + - Verify there are no VLANs or network isolation preventing communication + - Try rebooting both the device and Home Assistant ### 5. Initial Configuration From b7a66b2e87c91323a853002ff008b38346e0c265 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:02:05 +0100 Subject: [PATCH 060/109] Adding warnings --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 120bce4..ec919f4 100644 --- a/README.md +++ b/README.md @@ -137,8 +137,26 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. Initial flashing must be done via serial connection. We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experience. +> [!IMPORTANT] +> **SAFETY WARNINGS** +> - ALWAYS disconnect the device from mains power before opening +> - NEVER work on the device while connected to mains power +> - Ensure the device is completely powered off before making any connections +> - Keep your workspace clean, dry, and static-free +> - Use proper insulated tools when working with electronics +> - If unsure about any step, seek help from an experienced person + +> [!CAUTION] +>⚡ **CRITICAL: VOLTAGE WARNING** +> Using a UART adapter with voltage higher than 3.3V WILL DAMAGE YOUR DEVICE. +> Double-check your adapter's voltage before connecting - many common FTDI adapters +> default to 5V which will permanently damage the ESP32 chip. + #### Required Hardware -- USB-to-UART adapter (3.3V) +- USB-to-UART adapter: + - 3.3V logic level ONLY (DO NOT use 5V adapters) + - Must be capable of supplying at least 500mA + - Common adapters: CP2102, CH340, FTDI (ensure 3.3V setting) - Small Phillips screwdriver - 5 wires for connections (including one for BOOT to GND) From 09514e13316e983cd2501e15f1ae5c1a6f752822 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:04:14 +0100 Subject: [PATCH 061/109] Disable markdown lint --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ec919f4..4668617 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. Initial flashing must be done via serial connection. We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experience. + > [!IMPORTANT] > **SAFETY WARNINGS** > - ALWAYS disconnect the device from mains power before opening @@ -151,6 +152,7 @@ We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experi > Using a UART adapter with voltage higher than 3.3V WILL DAMAGE YOUR DEVICE. > Double-check your adapter's voltage before connecting - many common FTDI adapters > default to 5V which will permanently damage the ESP32 chip. + #### Required Hardware - USB-to-UART adapter: From 0779279d442ee72d9c552faf3173abead19d9758 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:10:26 +0100 Subject: [PATCH 062/109] Add dynamic version example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4668617..93b6800 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. You can also use a specific version tag for better control over updates: ```yaml - ref: v2025.1.3 # Replace with desired version (format: vYYYY.MM.nn) + ref: v[![version]][version] # Using specific version for controlled updates ``` 5. Click "Save" and then "Install" From ebd8a5432ab07f608ba18ac9573793e342c6e509 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:20:24 +0100 Subject: [PATCH 063/109] Minor changes as suggested by CodeRabbitAI --- README.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 93b6800..fcea48d 100644 --- a/README.md +++ b/README.md @@ -128,8 +128,12 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. You can also use a specific version tag for better control over updates: ```yaml - ref: v[![version]][version] # Using specific version for controlled updates + ref: v2024.12.2 # Using specific version for controlled updates ``` + + > [!NOTE] + > [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available + 5. Click "Save" and then "Install" ### 3. Device Flashing @@ -171,9 +175,9 @@ We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experi - TX → RX - RX → TX 4. Put device in flash mode: - - Connect the BOOT pin to GND using a jumper wire - - Power up the device (keeping BOOT connected to GND) - - Remove the BOOT to GND connection + - Temporarily connect the BOOT pin to GND using a jumper wire + - While holding BOOT to GND, power up the device + - After device powers up (wait a couple of seconds), remove the BOOT to GND connection 5. Visit [ESPHome Web](https://web.esphome.io) 6. Connect to your device and flash the firmware 7. After successful flash, device will restart and be ready for OTA updates @@ -196,8 +200,9 @@ through the ESPHome dashboard in your ESPHome add-on. After successful flashing: 1. Ensure your device and Home Assistant are on the same network -2. Device should be automatically discovered within a couple of minutes -3. Accept the discovery notification to add device +2. Device should be automatically discovered within 1-2 minutes +3. Accept the discovery notification in Home Assistant to add device + Note: If discovery takes longer than 5 minutes, proceed to troubleshooting steps 4. Device will appear in your Home Assistant Devices dashboard #### Troubleshooting Integration @@ -230,6 +235,9 @@ If the device isn't discovered automatically: - Haptic feedback - Audio feedback +> [!NOTE] +> Some changes may require a device restart + ## Usage After installation, you can: @@ -285,10 +293,11 @@ Note: For proper tracking and resolution: This project builds upon the work of several amazing projects and contributors: + - [SmartHome yourself - SONOFF TX Ultimate for ESPHome](https://github.com/SmartHome-yourself/sonoff-tx-ultimate-for-esphome) - [Un loco y su tecnología - Sonoff TX Ultimate with ESPHome](https://www.youtube.com/watch?v=58v8oqSQgXQ) -- [@PxPert](https://github.com/PxPert) - - [Sonoff TX Ultimate and Voice Assistant](https://community.home-assistant.io/t/sonoff-tx-ultimate-and-voice-assistant/682214?u=edwardtfn) +- [@PxPert](https://github.com/PxPert) - [Sonoff TX Ultimate and Voice Assistant](https://community.home-assistant.io/t/sonoff-tx-ultimate-and-voice-assistant/682214?u=edwardtfn) + Special thanks to all contributors and community members who help make this project better. From 05c40cf7b5b76e2064acd4ac2ce4351f0d64f51a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:24:39 +0100 Subject: [PATCH 064/109] Pinout in a table and test instructions --- README.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fcea48d..3d81669 100644 --- a/README.md +++ b/README.md @@ -170,10 +170,12 @@ We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experi 1. Open your TX Ultimate device carefully 2. Locate the programming header pins 3. Connect your USB-to-UART adapter: - - GND → GND - - 3.3V → 3.3V - - TX → RX - - RX → TX + | Adapter | Device | + |---------|--------| + | GND | GND | + | 3.3V | 3.3V | + | TX | RX | + | RX | TX | 4. Put device in flash mode: - Temporarily connect the BOOT pin to GND using a jumper wire - While holding BOOT to GND, power up the device @@ -200,7 +202,7 @@ through the ESPHome dashboard in your ESPHome add-on. After successful flashing: 1. Ensure your device and Home Assistant are on the same network -2. Device should be automatically discovered within 1-2 minutes +2. Device should be automatically discovered within 1–2 minutes 3. Accept the discovery notification in Home Assistant to add device Note: If discovery takes longer than 5 minutes, proceed to troubleshooting steps 4. Device will appear in your Home Assistant Devices dashboard @@ -234,6 +236,11 @@ If the device isn't discovered automatically: - Touch sensitivity - Haptic feedback - Audio feedback +4. Test your configuration: + - Verify each relay responds to controls + - Test configured button actions + - Confirm LED behavior matches settings + - Check haptic/audio feedback if enabled > [!NOTE] > Some changes may require a device restart From bd5091293eae054e647a59265ec744f36d75f28f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:29:50 +0100 Subject: [PATCH 065/109] Remove numbered sections --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3d81669..3aea939 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Before getting started, ensure you have: Follow these steps to get your TX Ultimate device up and running with ESPHome. -### 1. ESPHome Integration Setup +### ESPHome Integration Setup 1. Install ESPHome add-on in Home Assistant if not already installed: - Go to Settings → Add-ons → Add-on Store @@ -103,7 +103,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. 2. Start the ESPHome add-on and verify it's running 3. Access ESPHome dashboard through Home Assistant -### 2. Device Configuration +### Device Configuration 1. In ESPHome dashboard, click "+ New Device" 2. Name your device (e.g., "tx-ultimate-living-room") @@ -136,7 +136,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. 5. Click "Save" and then "Install" -### 3. Device Flashing +### Device Flashing Initial flashing must be done via serial connection. We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experience. @@ -198,7 +198,7 @@ Note: While these guides may use different firmware, the physical flashing proce After initial flashing, all future updates can be done wirelessly (OTA) through the ESPHome dashboard in your ESPHome add-on. -### 4. Home Assistant Integration +### Home Assistant Integration After successful flashing: 1. Ensure your device and Home Assistant are on the same network @@ -221,7 +221,7 @@ If the device isn't discovered automatically: - Verify there are no VLANs or network isolation preventing communication - Try rebooting both the device and Home Assistant -### 5. Initial Configuration +### Initial Configuration 1. In Home Assistant, navigate to: - Settings → Devices & Services → ESPHome From da9dfbf8081ae8863e783476f7bbd09ceee21ea2 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:31:57 +0100 Subject: [PATCH 066/109] Remove duplicated section label --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 3aea939..4d08ec6 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. 2. Start the ESPHome add-on and verify it's running 3. Access ESPHome dashboard through Home Assistant -### Device Configuration +### Setup Device 1. In ESPHome dashboard, click "+ New Device" 2. Name your device (e.g., "tx-ultimate-living-room") @@ -130,10 +130,8 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ```yaml ref: v2024.12.2 # Using specific version for controlled updates ``` - > [!NOTE] > [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available - 5. Click "Save" and then "Install" ### Device Flashing From a224cd5f866c74b80645a20cfbaf126484852170 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:33:24 +0100 Subject: [PATCH 067/109] Indentation on note --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d08ec6..0695c6e 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,8 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ```yaml ref: v2024.12.2 # Using specific version for controlled updates ``` - > [!NOTE] - > [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available + > [!NOTE] + > [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available 5. Click "Save" and then "Install" ### Device Flashing From 8b7fad76c1ccc6e262cd65ada11846c5f120e469 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:34:45 +0100 Subject: [PATCH 068/109] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 0695c6e..616f521 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ```yaml ref: v2024.12.2 # Using specific version for controlled updates ``` - > [!NOTE] - > [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available + **Note:** [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. 5. Click "Save" and then "Install" ### Device Flashing From b5a96387cb2ae125f114ca497d0264d1f073ec6e Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:35:10 +0100 Subject: [PATCH 069/109] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 616f521..64d0855 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ```yaml ref: v2024.12.2 # Using specific version for controlled updates ``` - **Note:** [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. + **Note:** [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. 5. Click "Save" and then "Install" ### Device Flashing From 8a343ab8fe03ae48ddcfa8c45b17ebb73124e9ef Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 10:39:51 +0100 Subject: [PATCH 070/109] CodeRabbitAI --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 64d0855..84ae042 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ### ESPHome Integration Setup -1. Install ESPHome add-on in Home Assistant if not already installed: +1. Install the ESPHome add-on in Home Assistant if not already installed: - Go to Settings → Add-ons → Add-on Store - Search for "ESPHome" - Click Install @@ -105,7 +105,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ### Setup Device -1. In ESPHome dashboard, click "+ New Device" +1. In the ESPHome dashboard, click "+ New Device" 2. Name your device (e.g., "tx-ultimate-living-room") 3. Select ESP32 as your device type 4. Copy this basic configuration to your new device: @@ -167,12 +167,14 @@ We recommend using [ESPHome Web](https://web.esphome.io) for the simplest experi 1. Open your TX Ultimate device carefully 2. Locate the programming header pins 3. Connect your USB-to-UART adapter: + | Adapter | Device | |---------|--------| | GND | GND | | 3.3V | 3.3V | | TX | RX | | RX | TX | + 4. Put device in flash mode: - Temporarily connect the BOOT pin to GND using a jumper wire - While holding BOOT to GND, power up the device From f84b9af1ee497325cec310612defd520b13c1155 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 27 Dec 2024 09:42:29 +0000 Subject: [PATCH 071/109] Bump version to 2024.12.25 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index a1f6a22..cf1c232 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.24 +2024.12.25 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index e41145d..c9639b1 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.24 +version: 2024.12.25 From ba69b43688cea11165dfe7c328c43490d42899e6 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 11:02:25 +0100 Subject: [PATCH 072/109] Adaptative logo --- Assets/Logo_dark.png | Bin 0 -> 168964 bytes Assets/Logo_dark.webp | Bin 0 -> 266974 bytes Assets/Logo_light.png | Bin 0 -> 109669 bytes README.md | 8 ++++++-- 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 Assets/Logo_dark.png create mode 100644 Assets/Logo_dark.webp create mode 100644 Assets/Logo_light.png diff --git a/Assets/Logo_dark.png b/Assets/Logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..640555eff7d38729f1e03afc4bed2769f6b83121 GIT binary patch literal 168964 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 literal 0 HcmV?d00001 diff --git a/Assets/Logo_dark.webp b/Assets/Logo_dark.webp new file mode 100644 index 0000000000000000000000000000000000000000..1a5cc8dd89594a9cbf75bd579ec8419dc03e161a GIT binary patch literal 266974 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 literal 0 HcmV?d00001 diff --git a/Assets/Logo_light.png b/Assets/Logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1be5af9565993147c3762757697e77a41b95b9 GIT binary patch literal 109669 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�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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index b6b6b29..a97830e 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo) -|  ![TX Ultimate Easy Logo](Assets/Logo.webp) | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | +|  TX Ultimate Easy Logo | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | | --- | :-- | @@ -167,5 +167,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file --- -TX Ultimate Easy Logo + + + + TX Ultimate Easy Logo + From 3e847bbd4afea58e115115464e7085365a87aa53 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 11:05:12 +0100 Subject: [PATCH 073/109] Allow for Inline HTML --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a97830e..1e9798d 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ [![Discord][discord-shield]](https://discord.gg/Db6WJWzWuf) [![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo) - + |  TX Ultimate Easy Logo | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | | --- | :-- | - + [version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version [version]: https://github.com/edwardtfn/TX-Ultimate-Easy/tags From e3abc6c6d57152383dd07e9f39fc710c41f261c2 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 11:07:31 +0100 Subject: [PATCH 074/109] Split table in lines --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e9798d..bf41027 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,13 @@ [![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo) -|  TX Ultimate Easy Logo | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | -| --- | :-- | +|   + + + + TX Ultimate Easy Logo + +| TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | [version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version From e8346e4436b4abc13e488800b9b047ce1df867e4 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Dec 2024 11:09:11 +0100 Subject: [PATCH 075/109] Revert the new line thing It broke the visual --- README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bf41027..1e9798d 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,8 @@ [![Buy me an ice-cream][buymeacoffee-shield]](https://www.buymeacoffee.com/edwardfirmo) -|   - - - - TX Ultimate Easy Logo - -| TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | +|  TX Ultimate Easy Logo | TX Ultimate Easy provides custom ESPHome firmware for Sonoff TX Ultimate devices. Our project focuses on user-friendly configuration through the Home Assistant UI, eliminating the need for manual YAML editing. Whether you're new to home automation or an experienced user, TX Ultimate Easy makes it simple to manage your device. | +| --- | :-- | [version-shield]: https://img.shields.io/github/v/tag/edwardtfn/TX-Ultimate-Easy?label=version From 1489bc52370d8bdca466924ff66877d8b33b555e Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 27 Dec 2024 10:12:23 +0000 Subject: [PATCH 076/109] Bump version to 2024.12.26 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index cf1c232..9d56291 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.25 +2024.12.26 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index c9639b1..147b01c 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.25 +version: 2024.12.26 From 133d571874147aab7486320050670b5392a7a97f Mon Sep 17 00:00:00 2001 From: "Jordan W. Cobb" Date: Fri, 27 Dec 2024 17:39:05 -0500 Subject: [PATCH 077/109] Update README.md Corrected path to TX-Ultimate-Easy-ESPHome.yaml --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b36d95..4922e5d 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. url: https://github.com/edwardtfn/TX-Ultimate-Easy ref: main # For latest stable release files: - - ESPHome/TX-Ultimate-Easy-ESPHome.yaml + - TX-Ultimate-Easy-ESPHome.yaml wifi: ssid: !secret wifi_ssid From 2e43160acb7d52d9680c8c9d44356b55ba8eb9a4 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sat, 28 Dec 2024 00:11:36 +0000 Subject: [PATCH 078/109] Bump version to 2024.12.27 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 9d56291..be422bb 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.26 +2024.12.27 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 147b01c..f50b709 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.26 +version: 2024.12.27 From 48ddfbf8b059425c19f86f3faa080603c00b2e17 Mon Sep 17 00:00:00 2001 From: Matthijs33 <57598126+Matthijs33@users.noreply.github.com> Date: Wed, 1 Jan 2025 14:32:17 +0100 Subject: [PATCH 079/109] Update TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml fixes #74 Value was "OFF" instead of "ON" --- ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml index 8da5856..45241a9 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml @@ -318,7 +318,7 @@ script: # - HW Vibration - binary_sensor.template.publish: id: bs_multi_touch - state: OFF # yamllint disable-line rule:truthy + state: ON # yamllint disable-line rule:truthy - id: touch_on_press mode: restart From 79b57304c74adc2bd7471c55ce01c6490c256e74 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 3 Jan 2025 22:53:46 +0100 Subject: [PATCH 080/109] Point users to `stable` tag. --- .github/workflows/versioning.yml | 8 +++----- README.md | 27 ++++++++++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/versioning.yml b/.github/workflows/versioning.yml index 31a94d5..95518c3 100644 --- a/.github/workflows/versioning.yml +++ b/.github/workflows/versioning.yml @@ -4,7 +4,6 @@ # 2. Manual dispatch - allows independent control over stable and latest tags --- - name: Version and Tags on: # yamllint disable-line rule:truthy @@ -56,10 +55,9 @@ jobs: - name: Update stable tag if: | - success() && ( - github.event_name == 'workflow_dispatch' && inputs.update_stable || - github.event_name == 'push' - ) + success() && + github.event_name == 'workflow_dispatch' && + inputs.update_stable run: | # Verify version bump was successful if [ ! -f "./versioning/VERSION" ]; then diff --git a/README.md b/README.md index 4922e5d..18b9bdc 100644 --- a/README.md +++ b/README.md @@ -111,26 +111,31 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. 4. Copy this basic configuration to your new device: ```yaml substitutions: - name: tx-ultimate-easy # Change this to your device name + name: tx-ultimate-easy friendly_name: TX Ultimate Easy - - packages: - remote_package: - url: https://github.com/edwardtfn/TX-Ultimate-Easy - ref: main # For latest stable release - files: - - TX-Ultimate-Easy-ESPHome.yaml - + wifi: ssid: !secret wifi_ssid password: !secret wifi_password - ``` + packages: + remote_package: + url: https://github.com/edwardtfn/TX-Ultimate-Easy + ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable + refresh: 5min + files: + - ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages + - ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages + # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support + ``` You can also use a specific version tag for better control over updates: ```yaml ref: v2024.12.2 # Using specific version for controlled updates ``` - **Note:** [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. + **Notes:** + - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. + - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/blob/main/TX-Ultimate-Easy-ESPHome.yaml) + for the latest version of this yaml. 5. Click "Save" and then "Install" ### Device Flashing From 037801e9617428a1c2f5e608b28ebdc729d318c2 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:31:14 +0100 Subject: [PATCH 081/109] Revert to media player and neopixelbus --- ESPHome/TX-Ultimate-Easy-ESPHome.yaml | 19 ++++++ ...Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 33 +++++++++ ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 4 +- ...TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml | 9 +-- .../TX-Ultimate-Easy-ESPHome_standard.yaml | 6 +- ...te-Easy-ESPHome_standard_media_player.yaml | 68 +++++++++++++++++++ TX-Ultimate-Easy-ESPHome.yaml | 3 +- 7 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome.yaml create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome.yaml new file mode 100644 index 0000000..061c27c --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome.yaml @@ -0,0 +1,19 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Basic (includes core plus non-essential, but recommended packages) ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +packages: + # yamllint disable rule:colons + core: !include TX-Ultimate-Easy-ESPHome_core.yaml + standard: !include TX-Ultimate-Easy-ESPHome_standard.yaml + # yamllint enable rule:colons +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 1346efb..c97a93e 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -11,13 +11,46 @@ ##### - For normal system use, modifications to this file are NOT required. ##### #################################################################################################### --- +packages: + standard_hw_speaker: !include TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml + bluetooth_proxy: +esp32: + framework: + type: esp-idf + sdkconfig_options: + CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" + CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" + CONFIG_ESP32_REV_MIN_3: "y" + CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" + CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" + CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" + CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" + CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" + CONFIG_SPIRAM_RODATA: "y" + CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" + esphome: platformio_options: build_flags: - -D TX_ULTIMATE_EASY_ADDON_BLE_PROXY +i2s_audio: !remove + +light: + - id: !extend light_full + platform: esp32_rmt_led_strip + rgb_order: GRB + rmt_channel: 1 + chipset: ws2812 + max_refresh_rate: 33ms + use_psram: false + type: !remove + variant: !remove + +media_player: !remove + script: - id: !extend dump_config_list_packages then: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 843ca1a..3c7b7e2 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -59,10 +59,8 @@ binary_sensor: - script.execute: dump_config_caller esp32: - board: esp32dev # adafruit_feather_esp32_v2 # esp32dev + board: esp32dev flash_size: 8MB - framework: - type: esp-idf esphome: name: ${name} diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml index 62579f7..76e3bf6 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml @@ -47,15 +47,12 @@ light: - id: light_full name: Light - All internal: true - platform: esp32_rmt_led_strip - rgb_order: GRB - rmt_channel: 1 - chipset: ws2812 num_leds: 32 pin: GPIO13 restore_mode: ${LIGHT_FULL_RESTORE_MODE} - max_refresh_rate: 33ms - use_psram: true + platform: neopixelbus + type: GRB + variant: WS2811 # Those lights are available based on the model selections - &light_partition_with_effects diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml index 0d9c0a7..bb044d2 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml @@ -13,9 +13,9 @@ --- packages: # yamllint disable rule:colons - core_hw_relays: !include TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml - core_hw_speaker: !include TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml - core_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + standard_hw_relays: !include TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml + standard_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml + standard_media_player: !include TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # yamllint enable rule:colons button: diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml new file mode 100644 index 0000000..d6985fb --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml @@ -0,0 +1,68 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome - Add-on - Media player ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +packages: + standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml + +esp32: + framework: + type: arduino + +esphome: + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_ADDON_MEDIA_PLAYER + +media_player: + - id: mp_media_player + name: Media Player + internal: false + platform: i2s_audio + i2s_dout_pin: GPIO15 + i2s_audio_id: if_i2s_audio + i2s_comm_fmt: msb + dac_type: external + mode: mono + mute_pin: + number: GPIO26 + inverted: true + allow_other_uses: true + +script: + - id: !extend dump_config_list_packages + then: + - script.wait: dump_config + - lambda: |- + // Check for requirements + #if !defined(TX_ULTIMATE_EASY_CORE) + #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." + #endif + #if !defined(TX_ULTIMATE_EASY_STANDARD_HW_AUDIO) + #error "The package TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml is required." + #endif + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - Media Player"); + +switch: + - id: sw_speaker_amplifier + name: Speaker - Amplifier + platform: gpio + pin: + number: GPIO26 + inverted: true + allow_other_uses: true + restore_mode: RESTORE_DEFAULT_ON + internal: true + entity_category: config +... diff --git a/TX-Ultimate-Easy-ESPHome.yaml b/TX-Ultimate-Easy-ESPHome.yaml index f8cff7b..6653f8e 100644 --- a/TX-Ultimate-Easy-ESPHome.yaml +++ b/TX-Ultimate-Easy-ESPHome.yaml @@ -16,11 +16,10 @@ wifi: packages: remote_package: url: https://github.com/edwardtfn/TX-Ultimate-Easy - ref: latest # Or you can specify a version, like `ref: v2024.12.6` + ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable refresh: 5min files: - ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml # Core (essential) packages - ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml # Non-essential, but recommended packages # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml # Adds BLE proxy support - # - ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml # Adds experimental Media Player (limited) ... From 9d64b099a4fb1db4f5c5d20080515ae8561e4cdc Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:34:38 +0100 Subject: [PATCH 082/109] Lint --- .github/workflows/versioning.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/versioning.yml b/.github/workflows/versioning.yml index 95518c3..ea3c246 100644 --- a/.github/workflows/versioning.yml +++ b/.github/workflows/versioning.yml @@ -55,8 +55,8 @@ jobs: - name: Update stable tag if: | - success() && - github.event_name == 'workflow_dispatch' && + success() && + github.event_name == 'workflow_dispatch' && inputs.update_stable run: | # Verify version bump was successful From ef4f412223b864e78ce4506e11e4fb9a4724a265 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:38:19 +0100 Subject: [PATCH 083/109] Split extensions --- .github/workflows/validate_esphome_beta.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index bd40471..143c514 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -8,10 +8,22 @@ permissions: on: # yamllint disable-line rule:truthy push: paths: - - "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory + - "**/*.yml" + - "**/*.yaml" + - "**/*.h" + - "**/*.cpp" + - "**/*.c" + - "**/*.py" + pull_request: paths: - - "**/*.{yml,yaml,h,cpp,c,py}" # Match any file with the extensions in any directory + - "**/*.yml" + - "**/*.yaml" + - "**/*.h" + - "**/*.cpp" + - "**/*.c" + - "**/*.py" + workflow_dispatch: concurrency: From e911482deb0e3db94ea86adc7d0336519b8152b7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:39:31 +0100 Subject: [PATCH 084/109] Lint --- .github/workflows/validate_esphome_beta.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate_esphome_beta.yml b/.github/workflows/validate_esphome_beta.yml index 143c514..dedada4 100644 --- a/.github/workflows/validate_esphome_beta.yml +++ b/.github/workflows/validate_esphome_beta.yml @@ -11,7 +11,7 @@ on: # yamllint disable-line rule:truthy - "**/*.yml" - "**/*.yaml" - "**/*.h" - - "**/*.cpp" + - "**/*.cpp" - "**/*.c" - "**/*.py" From 8d03105cafdf094bfc65e3fdc1d4d5f9c2c1cc24 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:54:08 +0100 Subject: [PATCH 085/109] Reorg tests --- .test/common.yaml | 5 ++++ .test/common_ard.yaml | 8 +++++++ .test/common_idf.yaml | 34 +++++++++++++++++++++++++++ .test/common_idf53.yaml | 10 ++++++++ .test/esphome_ard_basic.yaml | 9 +------ .test/esphome_ard_ble_proxy.yaml | 9 +------ .test/esphome_ard_core.yaml | 9 +------ .test/esphome_ard_hw_relays.yaml | 9 +------ .test/esphome_ard_hw_speaker.yaml | 9 +------ .test/esphome_ard_hw_vibration.yaml | 9 +------ .test/esphome_ard_media_player.yaml | 9 +------ .test/esphome_idf53_basic.yaml | 11 +-------- .test/esphome_idf53_ble_proxy.yaml | 11 +-------- .test/esphome_idf53_core.yaml | 11 +-------- .test/esphome_idf53_hw_relays.yaml | 11 +-------- .test/esphome_idf53_hw_speaker.yaml | 11 +-------- .test/esphome_idf53_hw_vibration.yaml | 11 +-------- .test/esphome_idf_basic.yaml | 9 +------ .test/esphome_idf_ble_proxy.yaml | 9 +------ .test/esphome_idf_core.yaml | 9 +------ .test/esphome_idf_hw_relays.yaml | 9 +------ .test/esphome_idf_hw_speaker.yaml | 9 +------ .test/esphome_idf_hw_vibration.yaml | 9 +------ 23 files changed, 76 insertions(+), 164 deletions(-) create mode 100644 .test/common.yaml create mode 100644 .test/common_ard.yaml create mode 100644 .test/common_idf.yaml create mode 100644 .test/common_idf53.yaml diff --git a/.test/common.yaml b/.test/common.yaml new file mode 100644 index 0000000..ef08688 --- /dev/null +++ b/.test/common.yaml @@ -0,0 +1,5 @@ +--- +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password +... diff --git a/.test/common_ard.yaml b/.test/common_ard.yaml new file mode 100644 index 0000000..fbd0402 --- /dev/null +++ b/.test/common_ard.yaml @@ -0,0 +1,8 @@ +--- +packages: + common: !include common.yaml + +esp32: + framework: + type: arduino +... diff --git a/.test/common_idf.yaml b/.test/common_idf.yaml new file mode 100644 index 0000000..9616d0d --- /dev/null +++ b/.test/common_idf.yaml @@ -0,0 +1,34 @@ +--- +packages: + common: !include common.yaml + +esp32: + framework: + type: esp-idf + sdkconfig_options: + CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" + CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" + CONFIG_ESP32_REV_MIN_3: "y" + CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" + CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" + CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" + CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" + CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" + CONFIG_SPIRAM_RODATA: "y" + CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" + +i2s_audio: !remove + +light: + - id: !extend light_full + platform: esp32_rmt_led_strip + rgb_order: GRB + rmt_channel: 1 + chipset: ws2812 + max_refresh_rate: 33ms + use_psram: false + type: !remove + variant: !remove + +media_player: !remove +... diff --git a/.test/common_idf53.yaml b/.test/common_idf53.yaml new file mode 100644 index 0000000..f2b9b5d --- /dev/null +++ b/.test/common_idf53.yaml @@ -0,0 +1,10 @@ +--- +packages: + common_idf: !include common_idf.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 +... diff --git a/.test/esphome_ard_basic.yaml b/.test/esphome_ard_basic.yaml index 20554a4..505acee 100644 --- a/.test/esphome_ard_basic.yaml +++ b/.test/esphome_ard_basic.yaml @@ -1,13 +1,6 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_ble_proxy.yaml b/.test/esphome_ard_ble_proxy.yaml index 86cc07c..097e273 100644 --- a/.test/esphome_ard_ble_proxy.yaml +++ b/.test/esphome_ard_ble_proxy.yaml @@ -1,14 +1,7 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_core.yaml b/.test/esphome_ard_core.yaml index 1b50c90..6b9bdba 100644 --- a/.test/esphome_ard_core.yaml +++ b/.test/esphome_ard_core.yaml @@ -1,12 +1,5 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_hw_relays.yaml b/.test/esphome_ard_hw_relays.yaml index 704ac7d..b12f6fe 100644 --- a/.test/esphome_ard_hw_relays.yaml +++ b/.test/esphome_ard_hw_relays.yaml @@ -1,13 +1,6 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_hw_speaker.yaml b/.test/esphome_ard_hw_speaker.yaml index 62272ca..e054db8 100644 --- a/.test/esphome_ard_hw_speaker.yaml +++ b/.test/esphome_ard_hw_speaker.yaml @@ -1,13 +1,6 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_hw_vibration.yaml b/.test/esphome_ard_hw_vibration.yaml index 5dbacea..b0f06f6 100644 --- a/.test/esphome_ard_hw_vibration.yaml +++ b/.test/esphome_ard_hw_vibration.yaml @@ -1,13 +1,6 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_ard_media_player.yaml b/.test/esphome_ard_media_player.yaml index 9a9f744..f12a529 100644 --- a/.test/esphome_ard_media_player.yaml +++ b/.test/esphome_ard_media_player.yaml @@ -1,15 +1,8 @@ --- packages: + common_arduino: !include common_ard.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml addon_media_player: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_media_player.yaml - -esp32: - framework: - type: arduino - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_basic.yaml b/.test/esphome_idf53_basic.yaml index 1dabf1f..c420d7f 100644 --- a/.test/esphome_idf53_basic.yaml +++ b/.test/esphome_idf53_basic.yaml @@ -1,15 +1,6 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_ble_proxy.yaml b/.test/esphome_idf53_ble_proxy.yaml index b17b6d2..9280dd2 100644 --- a/.test/esphome_idf53_ble_proxy.yaml +++ b/.test/esphome_idf53_ble_proxy.yaml @@ -1,16 +1,7 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_core.yaml b/.test/esphome_idf53_core.yaml index 18239c7..82b38fc 100644 --- a/.test/esphome_idf53_core.yaml +++ b/.test/esphome_idf53_core.yaml @@ -1,14 +1,5 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_hw_relays.yaml b/.test/esphome_idf53_hw_relays.yaml index d9f5bd0..628bb79 100644 --- a/.test/esphome_idf53_hw_relays.yaml +++ b/.test/esphome_idf53_hw_relays.yaml @@ -1,15 +1,6 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_hw_speaker.yaml b/.test/esphome_idf53_hw_speaker.yaml index 651ac37..4b4581f 100644 --- a/.test/esphome_idf53_hw_speaker.yaml +++ b/.test/esphome_idf53_hw_speaker.yaml @@ -1,15 +1,6 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf53_hw_vibration.yaml b/.test/esphome_idf53_hw_vibration.yaml index d0a5ed3..1bc90ad 100644 --- a/.test/esphome_idf53_hw_vibration.yaml +++ b/.test/esphome_idf53_hw_vibration.yaml @@ -1,15 +1,6 @@ --- packages: + common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml - -esp32: - framework: - type: esp-idf - version: 5.3.1 - platform_version: 6.9.0 - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_basic.yaml b/.test/esphome_idf_basic.yaml index ab3d202..d4d0357 100644 --- a/.test/esphome_idf_basic.yaml +++ b/.test/esphome_idf_basic.yaml @@ -1,13 +1,6 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_ble_proxy.yaml b/.test/esphome_idf_ble_proxy.yaml index c972d0f..a72bcdb 100644 --- a/.test/esphome_idf_ble_proxy.yaml +++ b/.test/esphome_idf_ble_proxy.yaml @@ -1,14 +1,7 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_core.yaml b/.test/esphome_idf_core.yaml index 846889a..6cb4742 100644 --- a/.test/esphome_idf_core.yaml +++ b/.test/esphome_idf_core.yaml @@ -1,12 +1,5 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_hw_relays.yaml b/.test/esphome_idf_hw_relays.yaml index d78b1b4..b746d8a 100644 --- a/.test/esphome_idf_hw_relays.yaml +++ b/.test/esphome_idf_hw_relays.yaml @@ -1,13 +1,6 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_relays_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_hw_speaker.yaml b/.test/esphome_idf_hw_speaker.yaml index 8bcf3ff..2ce797a 100644 --- a/.test/esphome_idf_hw_speaker.yaml +++ b/.test/esphome_idf_hw_speaker.yaml @@ -1,13 +1,6 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_speaker_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... diff --git a/.test/esphome_idf_hw_vibration.yaml b/.test/esphome_idf_hw_vibration.yaml index 8ac9039..30d7358 100644 --- a/.test/esphome_idf_hw_vibration.yaml +++ b/.test/esphome_idf_hw_vibration.yaml @@ -1,13 +1,6 @@ --- packages: + common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_hw_vibration_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml - -esp32: - framework: - type: esp-idf - -wifi: - ssid: !secret wifi_ssid - password: !secret wifi_password ... From 39cf0f2b1010aa0678a8065a6053caae81ae864f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 22:58:09 +0100 Subject: [PATCH 086/109] Do not remove media player from core --- .test/common_idf.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.test/common_idf.yaml b/.test/common_idf.yaml index 9616d0d..ebcaad5 100644 --- a/.test/common_idf.yaml +++ b/.test/common_idf.yaml @@ -17,8 +17,6 @@ esp32: CONFIG_SPIRAM_RODATA: "y" CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" -i2s_audio: !remove - light: - id: !extend light_full platform: esp32_rmt_led_strip @@ -29,6 +27,4 @@ light: use_psram: false type: !remove variant: !remove - -media_player: !remove ... From 95291c0381a7186fbd4c2a1ff987b9ce49967811 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 23:54:35 +0100 Subject: [PATCH 087/109] Remove non-essential packages --- .../TX-Ultimate-Easy-ESPHome_standard.yaml | 22 ------------------- README.md | 11 ++++++++++ 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml index bb044d2..75a6212 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml @@ -24,9 +24,6 @@ button: internal: false platform: restart -captive_portal: - id: ap_captive_portal - esphome: platformio_options: build_flags: @@ -50,23 +47,4 @@ script: - lambda: |- // Version information ESP_LOGCONFIG("standard", "ESPHome builder: %s", esphome_fw_version->state.c_str()); - -improv_serial: - id: serial_improv - -text_sensor: - - id: esphome_fw_version - name: ESPHome Version - platform: version - entity_category: diagnostic - internal: false - -time: - - id: time_source - platform: homeassistant - -web_server: - -wifi: - ap: ... diff --git a/README.md b/README.md index 18b9bdc..9af9bf3 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,17 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/blob/main/TX-Ultimate-Easy-ESPHome.yaml) for the latest version of this yaml. + + > [!IMPORTANT] + > Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi` are no longer included in the core package. If you need these components, you must add them manually to your local configuration file. For example: + > ```yaml + > # Add these to your configuration if needed + > web_server: + > captive_portal: + > wifi: + > ap: # Access point configuration + > ``` + 5. Click "Save" and then "Install" ### Device Flashing From a64c45b37b159e29c739cb1d5851b34d03c4d215 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 4 Jan 2025 23:58:05 +0100 Subject: [PATCH 088/109] Media Player is not compatible with IDF --- .../TX-Ultimate-Easy-ESPHome_standard_media_player.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml index d6985fb..0a4a339 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml @@ -14,10 +14,6 @@ packages: standard_hw_audio: !include TX-Ultimate-Easy-ESPHome_standard_hw_audio.yaml -esp32: - framework: - type: arduino - esphome: platformio_options: build_flags: @@ -44,6 +40,9 @@ script: - script.wait: dump_config - lambda: |- // Check for requirements + #ifdef USE_ESP_IDF + #error "This package is not compatible with ESP-IDF framework." + #endif #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif From e89adca5cb274e817f8d332973748934ba5abd43 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 00:34:40 +0100 Subject: [PATCH 089/109] Remove reference to `esphome_fw_version` --- ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml index 75a6212..a8766d3 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml @@ -46,5 +46,6 @@ script: then: - lambda: |- // Version information - ESP_LOGCONFIG("standard", "ESPHome builder: %s", esphome_fw_version->state.c_str()); + ESP_LOGCONFIG("standard", "ESPHome builder: " ESPHOME_VERSION); + ESP_LOGCONFIG("standard", "ESPHome build timestamp: %s", App.get_compilation_time().c_str()); ... From 81f0420987d43fb0daf767dcdd0ea42e74fbdc12 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 00:37:05 +0100 Subject: [PATCH 090/109] Lint --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9af9bf3..bb069d5 100644 --- a/README.md +++ b/README.md @@ -136,9 +136,11 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/blob/main/TX-Ultimate-Easy-ESPHome.yaml) for the latest version of this yaml. - > [!IMPORTANT] - > Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi` are no longer included in the core package. If you need these components, you must add them manually to your local configuration file. For example: + > Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi` + > are no longer included in the core package. If you need these components, + > you must add them manually to your local configuration file. + > For example: > ```yaml > # Add these to your configuration if needed > web_server: @@ -146,7 +148,6 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. > wifi: > ap: # Access point configuration > ``` - 5. Click "Save" and then "Install" ### Device Flashing From 12fd2d3747b0cfeea9a84d57c7ab97a1b6a1e87e Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 00:38:30 +0100 Subject: [PATCH 091/109] Lint --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index bb069d5..d282d26 100644 --- a/README.md +++ b/README.md @@ -136,20 +136,21 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/blob/main/TX-Ultimate-Easy-ESPHome.yaml) for the latest version of this yaml. - > [!IMPORTANT] - > Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi` - > are no longer included in the core package. If you need these components, - > you must add them manually to your local configuration file. - > For example: - > ```yaml - > # Add these to your configuration if needed - > web_server: - > captive_portal: - > wifi: - > ap: # Access point configuration - > ``` 5. Click "Save" and then "Install" +> [!IMPORTANT] +> Starting from version 2025.1.0, non-essential components like `web_server`, `captive_portal`, and `wifi` +> are no longer included in the core package. If you need these components, +> you must add them manually to your local configuration file. +> For example: +> ```yaml +> # Add these to your configuration if needed +> web_server: +> captive_portal: +> wifi: +> ap: # Access point configuration +> ``` + ### Device Flashing Initial flashing must be done via serial connection. From 56c613a70fcdfa30168608cae271e8268d3ad3f5 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 00:54:48 +0100 Subject: [PATCH 092/109] Remove `sw_speaker_amplifier` when the `media_player` is removed --- .test/esphome_idf53_basic.yaml | 5 +++++ .test/esphome_idf_basic.yaml | 5 +++++ ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 3 +++ 3 files changed, 13 insertions(+) diff --git a/.test/esphome_idf53_basic.yaml b/.test/esphome_idf53_basic.yaml index c420d7f..10024d4 100644 --- a/.test/esphome_idf53_basic.yaml +++ b/.test/esphome_idf53_basic.yaml @@ -3,4 +3,9 @@ packages: common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + +media_player: !remove + +switch: + - id: !remove sw_speaker_amplifier ... diff --git a/.test/esphome_idf_basic.yaml b/.test/esphome_idf_basic.yaml index d4d0357..82e7f09 100644 --- a/.test/esphome_idf_basic.yaml +++ b/.test/esphome_idf_basic.yaml @@ -3,4 +3,9 @@ packages: common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml + +media_player: !remove + +switch: + - id: !remove sw_speaker_amplifier ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index c97a93e..2161a7f 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -63,4 +63,7 @@ script: // Identify itself ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Add-on - BLE Proxy"); + +switch: + - id: !remove sw_speaker_amplifier ... From 036e62b277f04c0a84dfc61a42db12beedeab887 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 01:06:52 +0100 Subject: [PATCH 093/109] Remove check for framework type --- ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml index 0a4a339..32a8eb5 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml @@ -40,9 +40,6 @@ script: - script.wait: dump_config - lambda: |- // Check for requirements - #ifdef USE_ESP_IDF - #error "This package is not compatible with ESP-IDF framework." - #endif #if !defined(TX_ULTIMATE_EASY_CORE) #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." #endif From 5d80ce1117b40a92b867f1d322229e33ed4fc1eb Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 01:34:18 +0100 Subject: [PATCH 094/109] Do not remove attributes twice --- .test/esphome_idf53_ble_proxy.yaml | 7 ++++++- .test/esphome_idf_ble_proxy.yaml | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.test/esphome_idf53_ble_proxy.yaml b/.test/esphome_idf53_ble_proxy.yaml index 9280dd2..d4aa126 100644 --- a/.test/esphome_idf53_ble_proxy.yaml +++ b/.test/esphome_idf53_ble_proxy.yaml @@ -1,7 +1,12 @@ --- packages: - common_idf53: !include common_idf53.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml + +esp32: + framework: + type: esp-idf + version: 5.3.1 + platform_version: 6.9.0 ... diff --git a/.test/esphome_idf_ble_proxy.yaml b/.test/esphome_idf_ble_proxy.yaml index a72bcdb..49d28cc 100644 --- a/.test/esphome_idf_ble_proxy.yaml +++ b/.test/esphome_idf_ble_proxy.yaml @@ -1,6 +1,5 @@ --- packages: - common_idf: !include common_idf.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml From 5988681132be6596df65edfc2abb1f7214f02aa4 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 11:02:46 +0100 Subject: [PATCH 095/109] Include common --- .test/esphome_idf53_ble_proxy.yaml | 1 + .test/esphome_idf_ble_proxy.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/.test/esphome_idf53_ble_proxy.yaml b/.test/esphome_idf53_ble_proxy.yaml index d4aa126..5acf57b 100644 --- a/.test/esphome_idf53_ble_proxy.yaml +++ b/.test/esphome_idf53_ble_proxy.yaml @@ -1,5 +1,6 @@ --- packages: + common: !include common.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml diff --git a/.test/esphome_idf_ble_proxy.yaml b/.test/esphome_idf_ble_proxy.yaml index 49d28cc..dc303a6 100644 --- a/.test/esphome_idf_ble_proxy.yaml +++ b/.test/esphome_idf_ble_proxy.yaml @@ -1,5 +1,6 @@ --- packages: + common: !include common.yaml core_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml standard_package: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml addon_bluetooth_proxy: !include ../ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml From e47726dc4710f5f6225fc38cf27eac5f669a2a2a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:40:52 +0100 Subject: [PATCH 096/109] Advanced settings with granular package selection Resolves #86 --- ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml | 301 +--------------- .../TX-Ultimate-Easy-ESPHome_core_common.yaml | 323 ++++++++++++++++++ .../TX-Ultimate-Easy-ESPHome_standard.yaml | 31 -- README.md | 35 +- TX-Ultimate-Easy-ESPHome_advanced.yaml | 38 +++ 5 files changed, 396 insertions(+), 332 deletions(-) create mode 100644 ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml create mode 100644 TX-Ultimate-Easy-ESPHome_advanced.yaml diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml index 3c7b7e2..6672dd3 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core.yaml @@ -11,310 +11,11 @@ ##### - For normal system use, modifications to this file are NOT required. ##### #################################################################################################### --- -substitutions: - name: tx-ultimate-easy - friendly_name: TX Ultimate Easy - - <<: !include ../versioning/VERSION_YAML - - TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)" - TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)" - - TX_MODEL_1_GANG_TEXT: "1 Gang" - TX_MODEL_2_GANG_TEXT: "2 Gang" - TX_MODEL_3_GANG_TEXT: "3 Gang" - TX_MODEL_4_GANG_TEXT: "4 Gang" - - DUMP_CONFIG_CALLER_DELAY: 10s # Delay to dump config after requested - packages: # yamllint disable rule:colons + core_common: !include TX-Ultimate-Easy-ESPHome_core_common.yaml core_hw_buttons: !include TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml core_hw_leds: !include TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml core_hw_touch: !include TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # yamllint enable rule:colons - -api: - id: api_server - on_client_connected: - then: - - script.execute: dump_config_caller - - script.execute: publish_device_info - -binary_sensor: - - id: bs_pending_restart - name: Pending Restart Status - internal: false - disabled_by_default: false - platform: template - entity_category: diagnostic - device_class: problem - on_state: - then: - - lambda: |- - if (x) - ESP_LOGW("core", "Pending restart: YES"); - else - ESP_LOGCONFIG("core", "Pending restart: No"); - - script.execute: dump_config_caller - -esp32: - board: esp32dev - flash_size: 8MB - -esphome: - name: ${name} - friendly_name: ${friendly_name} - comment: TX Ultimate Easy - project: - name: "edwardtfn.tx_ultimate_easy" - version: ${version} - platformio_options: - build_flags: - - -D TX_ULTIMATE_EASY_CORE - - on_boot: - - priority: 700 - then: - - script.execute: boot_initialize - - - priority: 600 # This is where most sensors are set up. - then: - - script.execute: boot_sequence - - - priority: -100 # At this priority, pretty much everything should already be initialized. - then: - - script.execute: boot_done - -globals: - - id: is_us_model - type: bool - restore_value: true - initial_value: 'false' - - - id: gang_count - type: uint8_t - restore_value: true - initial_value: '0' - - - id: gang_count_plural_suffix - type: std::string - restore_value: true - max_restore_data_length: 3 - # initial_value: "''" - -logger: - level: DEBUG - -ota: - platform: esphome - -psram: - mode: octal - speed: 80MHz - -script: - - id: api_send_ha_event_boot - mode: queued - parameters: - type: string - then: - - homeassistant.event: - event: esphome.tx_ultimate_easy - data: - device_name: !lambda return tx_device_name->state.c_str(); - firmware: ${version} - domain: boot - type: !lambda return type.c_str(); - - - id: boot_done - mode: restart - then: - - script.execute: - id: api_send_ha_event_boot - type: done - - - id: boot_initialize - mode: restart - then: - # Extended by: - # - HW Buttons - # - HW Relays - # - HW Touch - - script.execute: - id: api_send_ha_event_boot - type: start - - wait_until: - condition: - - lambda: return sl_tx_model_format->active_index().has_value(); - - lambda: return sl_tx_model_gang->active_index().has_value(); - - lambda: |- - id(is_us_model) = (sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}"); - id(gang_count) = sl_tx_model_gang->active_index().value() + 1; - if (id(gang_count) < 1 || id(gang_count) > 4) { - ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, id(gang_count)); - } - id(gang_count_plural_suffix) = id(gang_count) > 1 ? "s" : ""; - - - id: boot_sequence - mode: restart - then: - - script.execute: publish_device_info - - binary_sensor.template.publish: - id: bs_pending_restart - state: false - - - id: dump_config - mode: restart - then: - # Extended by all modules - - lambda: |- - // Device identification - ESP_LOGCONFIG("core", "Device friendly name: ${friendly_name}"); - ESP_LOGCONFIG("core", "Device name: ${name}"); - ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str()); - ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str()); - - dump_config_versions->execute(); - - // Framework detection - #ifdef USE_ARDUINO - ESP_LOGCONFIG("core", "Framework: Arduino"); - #elif defined(USE_ESP_IDF) - ESP_LOGCONFIG("core", "Framework: ESP-IDF"); - #else - ESP_LOGW("core", "Framework: UNKNOWN"); - #endif - - // Model configuration - ESP_LOGCONFIG("core", "Model format (selected): %s", sl_tx_model_format->state.c_str()); - ESP_LOGCONFIG("core", "Model format (detected): %s", id(is_us_model) ? "US" : "EU"); - ESP_LOGCONFIG("core", "Gangs (selected): %s", sl_tx_model_gang->state.c_str()); - ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count_plural_suffix).c_str()); - - // System state - if (bs_pending_restart->state) - ESP_LOGW("core", "Pending restart: YES"); - else - ESP_LOGCONFIG("core", "Pending restart: No"); - - - id: dump_config_caller - mode: restart - then: - - delay: ${DUMP_CONFIG_CALLER_DELAY} - - script.execute: dump_config - - script.wait: dump_config - - script.execute: dump_config_list_packages - - - id: dump_config_list_packages - mode: restart - then: - - script.wait: dump_config - - lambda: |- - ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, "Installed packages:"); - - // Identify itself - ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core"); - - - id: dump_config_versions - mode: restart - then: - - lambda: |- - // Version information - ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); - - - id: publish_device_info - mode: restart - then: - - lambda: |- - tx_fw_version->publish_state("${version}"); - tx_device_name->publish_state(App.get_name().c_str()); - -select: - - id: sl_tx_model_format - name: Model (Format) - platform: template - options: - - "${TX_MODEL_FORMAT_EU_TEXT}" - - "${TX_MODEL_FORMAT_US_TEXT}" - initial_option: "${TX_MODEL_FORMAT_EU_TEXT}" - optimistic: true - restore_value: true - internal: false - entity_category: config - disabled_by_default: false - icon: mdi:tablet-cellphone - on_value: - then: - - binary_sensor.template.publish: - id: bs_pending_restart - state: true - - lambda: |- - id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}"); - ESP_LOGI("core", "New model selected: %s", id(is_us_model) ? "US" : "EU"); - - - id: sl_tx_model_gang - name: Model (Gang) - platform: template - options: - - "${TX_MODEL_1_GANG_TEXT}" - - "${TX_MODEL_2_GANG_TEXT}" - - "${TX_MODEL_3_GANG_TEXT}" - - "${TX_MODEL_4_GANG_TEXT}" - initial_option: "${TX_MODEL_1_GANG_TEXT}" - optimistic: true - restore_value: true - internal: false - entity_category: config - disabled_by_default: false - icon: mdi:dip-switch - on_value: - then: - - binary_sensor.template.publish: - id: bs_pending_restart - state: true - - lambda: |- - id(gang_count) = static_cast(i) + 1; - ESP_LOGI("core", "New model selected: %" PRIu8 "-%s", id(gang_count), id(gang_count) > 1 ? "Gangs" : "Gang"); - tx_ultimate->set_gang_count(id(gang_count)); - -text_sensor: - - id: tx_fw_version - name: TX Ultimate Easy Firmware Version - platform: template - entity_category: diagnostic - icon: mdi:tag-text-outline - internal: false - update_interval: never - lambda: |- - return {"${version}"}; - - - id: tx_device_name - name: Device Name - platform: template - icon: mdi:identifier - entity_category: diagnostic - internal: false - disabled_by_default: false - update_interval: never - lambda: |- - return {"${name}"}; - filters: - - lambda: |- - const std::string raw_name = x; - std::string result; - bool last_was_underscore = false; - for (const char& c : raw_name) { - if (isalnum(c)) { - result += tolower(c); // Add alphanumeric characters as lowercase - last_was_underscore = false; - } else if (!last_was_underscore) { // Replace non-alphanumeric with '_' but avoid consecutive '_' - result += '_'; - last_was_underscore = true; - } - } - return result; - -wifi: - id: wifi_component ... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml new file mode 100644 index 0000000..150b46c --- /dev/null +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml @@ -0,0 +1,323 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Purpose: ESPHome Core - Common ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### NOTE: ##### +##### - Make changes ONLY if absolutely necessary and you have the required knowledge. ##### +##### - For normal system use, modifications to this file are NOT required. ##### +#################################################################################################### +--- +substitutions: + name: tx-ultimate-easy + friendly_name: TX Ultimate Easy + + <<: !include ../versioning/VERSION_YAML + + TX_MODEL_FORMAT_EU_TEXT: "EU (Square, T5-xC-86)" + TX_MODEL_FORMAT_US_TEXT: "US (Rectangle, T5-xC-120)" + + TX_MODEL_1_GANG_TEXT: "1 Gang" + TX_MODEL_2_GANG_TEXT: "2 Gang" + TX_MODEL_3_GANG_TEXT: "3 Gang" + TX_MODEL_4_GANG_TEXT: "4 Gang" + + DUMP_CONFIG_CALLER_DELAY: 10s # Delay to dump config after requested + + +api: + id: api_server + on_client_connected: + then: + - script.execute: dump_config_caller + - script.execute: publish_device_info + +binary_sensor: + - id: bs_pending_restart + name: Pending Restart Status + internal: false + disabled_by_default: false + platform: template + entity_category: diagnostic + device_class: problem + on_state: + then: + - lambda: |- + if (x) + ESP_LOGW("core", "Pending restart: YES"); + else + ESP_LOGCONFIG("core", "Pending restart: No"); + - script.execute: dump_config_caller + +button: + - id: bt_restart + name: Restart + internal: false + platform: restart + +esp32: + board: esp32dev + flash_size: 8MB + +esphome: + name: ${name} + friendly_name: ${friendly_name} + comment: TX Ultimate Easy + project: + name: "edwardtfn.tx_ultimate_easy" + version: ${version} + platformio_options: + build_flags: + - -D TX_ULTIMATE_EASY_CORE + + on_boot: + - priority: 700 + then: + - script.execute: boot_initialize + + - priority: 600 # This is where most sensors are set up. + then: + - script.execute: boot_sequence + + - priority: -100 # At this priority, pretty much everything should already be initialized. + then: + - script.execute: boot_done + +globals: + - id: is_us_model + type: bool + restore_value: true + initial_value: 'false' + + - id: gang_count + type: uint8_t + restore_value: true + initial_value: '0' + + - id: gang_count_plural_suffix + type: std::string + restore_value: true + max_restore_data_length: 3 + # initial_value: "''" + +logger: + level: DEBUG + +ota: + platform: esphome + +psram: + mode: octal + speed: 80MHz + +script: + - id: api_send_ha_event_boot + mode: queued + parameters: + type: string + then: + - homeassistant.event: + event: esphome.tx_ultimate_easy + data: + device_name: !lambda return tx_device_name->state.c_str(); + firmware: ${version} + domain: boot + type: !lambda return type.c_str(); + + - id: boot_done + mode: restart + then: + - script.execute: + id: api_send_ha_event_boot + type: done + + - id: boot_initialize + mode: restart + then: + # Extended by: + # - HW Buttons + # - HW Relays + # - HW Touch + - script.execute: + id: api_send_ha_event_boot + type: start + - wait_until: + condition: + - lambda: return sl_tx_model_format->active_index().has_value(); + - lambda: return sl_tx_model_gang->active_index().has_value(); + - lambda: |- + id(is_us_model) = (sl_tx_model_format->state == "${TX_MODEL_FORMAT_US_TEXT}"); + id(gang_count) = sl_tx_model_gang->active_index().value() + 1; + if (id(gang_count) < 1 || id(gang_count) > 4) { + ESP_LOGE("core_hw_leds", "Invalid number of gangs: %" PRIu8, id(gang_count)); + } + id(gang_count_plural_suffix) = id(gang_count) > 1 ? "s" : ""; + + - id: boot_sequence + mode: restart + then: + - script.execute: publish_device_info + - binary_sensor.template.publish: + id: bs_pending_restart + state: false + + - id: dump_config + mode: restart + then: + # Extended by all modules + - lambda: |- + // Device identification + ESP_LOGCONFIG("core", "Device friendly name: ${friendly_name}"); + ESP_LOGCONFIG("core", "Device name: ${name}"); + ESP_LOGCONFIG("core", "Device name (HA): %s", tx_device_name->state.c_str()); + ESP_LOGCONFIG("core", "Device hostname: %s", App.get_name().c_str()); + + dump_config_versions->execute(); + + // Framework detection + #ifdef USE_ARDUINO + ESP_LOGCONFIG("core", "Framework: Arduino"); + #elif defined(USE_ESP_IDF) + ESP_LOGCONFIG("core", "Framework: ESP-IDF"); + #else + ESP_LOGW("core", "Framework: UNKNOWN"); + #endif + + // Model configuration + ESP_LOGCONFIG("core", "Model format (selected): %s", sl_tx_model_format->state.c_str()); + ESP_LOGCONFIG("core", "Model format (detected): %s", id(is_us_model) ? "US" : "EU"); + ESP_LOGCONFIG("core", "Gangs (selected): %s", sl_tx_model_gang->state.c_str()); + ESP_LOGCONFIG("core", "Gangs (detected): %" PRIu8 "-Gang%s", id(gang_count), id(gang_count_plural_suffix).c_str()); + + // System state + if (bs_pending_restart->state) + ESP_LOGW("core", "Pending restart: YES"); + else + ESP_LOGCONFIG("core", "Pending restart: No"); + + - id: dump_config_caller + mode: restart + then: + - delay: ${DUMP_CONFIG_CALLER_DELAY} + - script.execute: dump_config + - script.wait: dump_config + - script.execute: dump_config_list_packages + + - id: dump_config_list_packages + mode: restart + then: + - script.wait: dump_config + - lambda: |- + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, "Installed packages:"); + + // Identify itself + ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Core"); + + - id: dump_config_versions + mode: restart + then: + - lambda: |- + // Version information + ESP_LOGCONFIG("core", "TX Ultimate firmware version: ${version}"); + // ESPHome builder information + ESP_LOGCONFIG("core", "ESPHome builder: " ESPHOME_VERSION); + ESP_LOGCONFIG("core", "ESPHome build timestamp: %s", App.get_compilation_time().c_str()); + + - id: publish_device_info + mode: restart + then: + - lambda: |- + tx_fw_version->publish_state("${version}"); + tx_device_name->publish_state(App.get_name().c_str()); + +select: + - id: sl_tx_model_format + name: Model (Format) + platform: template + options: + - "${TX_MODEL_FORMAT_EU_TEXT}" + - "${TX_MODEL_FORMAT_US_TEXT}" + initial_option: "${TX_MODEL_FORMAT_EU_TEXT}" + optimistic: true + restore_value: true + internal: false + entity_category: config + disabled_by_default: false + icon: mdi:tablet-cellphone + on_value: + then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true + - lambda: |- + id(is_us_model) = (x == "${TX_MODEL_FORMAT_US_TEXT}"); + ESP_LOGI("core", "New model selected: %s", id(is_us_model) ? "US" : "EU"); + + - id: sl_tx_model_gang + name: Model (Gang) + platform: template + options: + - "${TX_MODEL_1_GANG_TEXT}" + - "${TX_MODEL_2_GANG_TEXT}" + - "${TX_MODEL_3_GANG_TEXT}" + - "${TX_MODEL_4_GANG_TEXT}" + initial_option: "${TX_MODEL_1_GANG_TEXT}" + optimistic: true + restore_value: true + internal: false + entity_category: config + disabled_by_default: false + icon: mdi:dip-switch + on_value: + then: + - binary_sensor.template.publish: + id: bs_pending_restart + state: true + - lambda: |- + id(gang_count) = static_cast(i) + 1; + ESP_LOGI("core", "New model selected: %" PRIu8 "-%s", id(gang_count), id(gang_count) > 1 ? "Gangs" : "Gang"); + tx_ultimate->set_gang_count(id(gang_count)); + +text_sensor: + - id: tx_fw_version + name: TX Ultimate Easy Firmware Version + platform: template + entity_category: diagnostic + icon: mdi:tag-text-outline + internal: false + update_interval: never + lambda: |- + return {"${version}"}; + + - id: tx_device_name + name: Device Name + platform: template + icon: mdi:identifier + entity_category: diagnostic + internal: false + disabled_by_default: false + update_interval: never + lambda: |- + return {"${name}"}; + filters: + - lambda: |- + const std::string raw_name = x; + std::string result; + bool last_was_underscore = false; + for (const char& c : raw_name) { + if (isalnum(c)) { + result += tolower(c); // Add alphanumeric characters as lowercase + last_was_underscore = false; + } else if (!last_was_underscore) { // Replace non-alphanumeric with '_' but avoid consecutive '_' + result += '_'; + last_was_underscore = true; + } + } + return result; + +wifi: + id: wifi_component +... diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml index a8766d3..17cbe16 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_standard.yaml @@ -17,35 +17,4 @@ packages: standard_hw_vibration: !include TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml standard_media_player: !include TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # yamllint enable rule:colons - -button: - - id: bt_restart - name: Restart - internal: false - platform: restart - -esphome: - platformio_options: - build_flags: - - -D TX_ULTIMATE_EASY_STANDARD - -script: - - id: !extend dump_config_list_packages - then: - - script.wait: dump_config - - lambda: |- - // Check for requirements - #if !defined(TX_ULTIMATE_EASY_CORE) - #error "The package TX-Ultimate-Easy-ESPHome_core.yaml is required." - #endif - - // Identify itself - ESP_LOGCONFIG(ESPHOME_PROJECT_NAME, " - Standard"); - - - id: !extend dump_config_versions - then: - - lambda: |- - // Version information - ESP_LOGCONFIG("standard", "ESPHome builder: " ESPHOME_VERSION); - ESP_LOGCONFIG("standard", "ESPHome build timestamp: %s", App.get_compilation_time().c_str()); ... diff --git a/README.md b/README.md index d282d26..986fe8a 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. ``` **Notes:** - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/tags) for a full list of versions available. - - [Click here](https://github.com/edwardtfn/TX-Ultimate-Easy/blob/main/TX-Ultimate-Easy-ESPHome.yaml) + - [Click here](TX-Ultimate-Easy-ESPHome.yaml) for the latest version of this yaml. 5. Click "Save" and then "Install" @@ -151,6 +151,39 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. > ap: # Access point configuration > ``` +### Advanced Settings +For more granular control over components, you can use our [advanced configuration template](TX-Ultimate-Easy-ESPHome_advanced.yaml). This template allows you to selectively include specific packages, which can be useful for: + +- Troubleshooting specific components +- Reducing memory usage by excluding unused features +- Customizing functionality for specific use cases + +Here's an example of the advanced configuration: +```yaml +packages: + remote_package: + url: https://github.com/edwardtfn/TX-Ultimate-Easy + ref: stable + refresh: 5min + files: + # Core (essential) packages + - ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml # Basic shared settings + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml # Button logic + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml # LED configuration + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # Touch panel support + + # Optional but recommended packages + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml # Relay control + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback + + # Audio options (use none or choose only one - using both will fail) + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # Media player (Recommended for most users) + # - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml # Basic speaker +``` + +> [!NOTE] +> Use the advanced configuration with caution. Excluding core packages may cause instability or reduced functionality. + ### Device Flashing Initial flashing must be done via serial connection. diff --git a/TX-Ultimate-Easy-ESPHome_advanced.yaml b/TX-Ultimate-Easy-ESPHome_advanced.yaml new file mode 100644 index 0000000..eb66df9 --- /dev/null +++ b/TX-Ultimate-Easy-ESPHome_advanced.yaml @@ -0,0 +1,38 @@ +#################################################################################################### +##### TX Ultimate Easy for ESPHome ##### +##### Repository: https://github.com/edwardtfn/TX-Ultimate-Easy ##### +#################################################################################################### +##### Author: edwardtfn - https://github.com/edwardtfn - https://buymeacoffee.com/edwardfirmo ##### +#################################################################################################### +##### WARNING: This is an advanced configuration template. Use with caution as improper ##### +##### configuration may lead to reduced functionality or system instability. ##### +#################################################################################################### +--- +substitutions: + name: tx-ultimate-easy-adv + friendly_name: TX Ultimate Easy Advanced + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + +packages: + remote_package: + url: https://github.com/edwardtfn/TX-Ultimate-Easy + ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable + refresh: 5min + files: + # Core (essential) packages - Do not disable these unless you know what you're doing + - ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml # Basic shared settings + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_buttons.yaml # Button logic + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_leds.yaml # LED configuration + - ESPHome/TX-Ultimate-Easy-ESPHome_core_hw_touch.yaml # Touch panel support + + # Optional functionality - Can be enabled/disabled as needed + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml # Relay control + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback + + # Audio options (use none or choose only one - using both will fail) + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # Media player (Recommended for most users) + # - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_speaker.yaml # Basic speaker +... From 9bae016573fa0f7ac1e587cee6458ac244829eb5 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:43:08 +0100 Subject: [PATCH 097/109] Lint --- TX-Ultimate-Easy-ESPHome_advanced.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TX-Ultimate-Easy-ESPHome_advanced.yaml b/TX-Ultimate-Easy-ESPHome_advanced.yaml index eb66df9..9ffd141 100644 --- a/TX-Ultimate-Easy-ESPHome_advanced.yaml +++ b/TX-Ultimate-Easy-ESPHome_advanced.yaml @@ -10,7 +10,7 @@ --- substitutions: name: tx-ultimate-easy-adv - friendly_name: TX Ultimate Easy Advanced + friendly_name: TX Ultimate Easy Advanced wifi: ssid: !secret wifi_ssid @@ -30,7 +30,7 @@ packages: # Optional functionality - Can be enabled/disabled as needed - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_relays.yaml # Relay control - - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback + - ESPHome/TX-Ultimate-Easy-ESPHome_standard_hw_vibration.yaml # Haptic feedback # Audio options (use none or choose only one - using both will fail) - ESPHome/TX-Ultimate-Easy-ESPHome_standard_media_player.yaml # Media player (Recommended for most users) From acb602c4ca5f6e455b8bcc387cab49cbcd13dda8 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:44:48 +0100 Subject: [PATCH 098/109] Lint --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 986fe8a..cccd393 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,9 @@ Follow these steps to get your TX Ultimate device up and running with ESPHome. > ``` ### Advanced Settings -For more granular control over components, you can use our [advanced configuration template](TX-Ultimate-Easy-ESPHome_advanced.yaml). This template allows you to selectively include specific packages, which can be useful for: +For more granular control over components, +you can use our [advanced configuration template](TX-Ultimate-Easy-ESPHome_advanced.yaml). +This template allows you to selectively include specific packages, which can be useful for: - Troubleshooting specific components - Reducing memory usage by excluding unused features From 6bdf6e97b7200132d778204124efeb17dd3c5891 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:51:22 +0100 Subject: [PATCH 099/109] Move sdkconfig to component --- .../TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml | 11 ----------- components/tx_ultimate_easy/__init__.py | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml index 2161a7f..292ed0a 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_addon_ble_proxy.yaml @@ -19,17 +19,6 @@ bluetooth_proxy: esp32: framework: type: esp-idf - sdkconfig_options: - CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" - CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" - CONFIG_ESP32_REV_MIN_3: "y" - CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" - CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" - CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" - CONFIG_SPIRAM_RODATA: "y" - CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" esphome: platformio_options: diff --git a/components/tx_ultimate_easy/__init__.py b/components/tx_ultimate_easy/__init__.py index 7120ead..eef1a13 100644 --- a/components/tx_ultimate_easy/__init__.py +++ b/components/tx_ultimate_easy/__init__.py @@ -109,3 +109,17 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) await register_tx_ultimate_easy(var, config) + + if CORE.using_esp_idf: + add_idf_sdkconfig_option("CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST", True) + add_idf_sdkconfig_option("CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY", True) + add_idf_sdkconfig_option("CONFIG_ESP32_REV_MIN_3", True) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_BUFFER", True) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT", True) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", True) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) + + cg.add_define("USE_TX_ULTIMATE_EASY") From 8a4009dd7e6097715d83fdc1eb8ee44b24d258c7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:58:45 +0100 Subject: [PATCH 100/109] Move `sdkconfig_options` to component --- .test/common_idf.yaml | 11 ----------- README.md | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.test/common_idf.yaml b/.test/common_idf.yaml index ebcaad5..fb9297c 100644 --- a/.test/common_idf.yaml +++ b/.test/common_idf.yaml @@ -5,17 +5,6 @@ packages: esp32: framework: type: esp-idf - sdkconfig_options: - CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y" - CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y" - CONFIG_ESP32_REV_MIN_3: "y" - CONFIG_MBEDTLS_DYNAMIC_BUFFER: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT: "y" - CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA: "y" - CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y" - CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY: "y" - CONFIG_SPIRAM_RODATA: "y" - CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP: "y" light: - id: !extend light_full diff --git a/README.md b/README.md index cccd393..c7f64d0 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ Here's an example of the advanced configuration: packages: remote_package: url: https://github.com/edwardtfn/TX-Ultimate-Easy - ref: stable + ref: stable # Or you can specify a version, like `ref: v2024.12.6` or `ref: latest` to the latest non-stable refresh: 5min files: # Core (essential) packages From a59f667e7dc6e389339ed2d2cf4702ab62ec890b Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 6 Jan 2025 16:00:59 +0000 Subject: [PATCH 101/109] Bump version to 2025.1.1 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index be422bb..7343555 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2024.12.27 +2025.1.1 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index f50b709..56e9f9d 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2024.12.27 +version: 2025.1.1 From ba3fc890327151aebc7de60fc5f45e4f05ee68eb Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 6 Jan 2025 16:01:26 +0000 Subject: [PATCH 102/109] Bump version to 2025.1.2 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 7343555..67df3ce 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2025.1.1 +2025.1.2 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 56e9f9d..7cec167 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2025.1.1 +version: 2025.1.2 From b6e3f41952af794e49c5322649f0ace108c4aa69 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:15:27 +0100 Subject: [PATCH 103/109] Fix `name 'CORE' is not defined` --- ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml | 1 - components/tx_ultimate_easy/__init__.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml b/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml index 150b46c..6f72818 100644 --- a/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml +++ b/ESPHome/TX-Ultimate-Easy-ESPHome_core_common.yaml @@ -101,7 +101,6 @@ globals: type: std::string restore_value: true max_restore_data_length: 3 - # initial_value: "''" logger: level: DEBUG diff --git a/components/tx_ultimate_easy/__init__.py b/components/tx_ultimate_easy/__init__.py index eef1a13..7a7be12 100644 --- a/components/tx_ultimate_easy/__init__.py +++ b/components/tx_ultimate_easy/__init__.py @@ -1,11 +1,11 @@ import esphome.codegen as cg import esphome.config_validation as cv +from esphome import automation from esphome.components import uart from esphome.const import ( CONF_ID, ) - -from esphome import automation +from esphome.core import CORE CODEOWNERS = ["@edwardtfn"] DEPENDENCIES = ['uart'] From fe222ffe32b869e98d443bb10fae224dc864fae3 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 7 Jan 2025 07:17:53 +0000 Subject: [PATCH 104/109] Bump version to 2025.1.3 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 67df3ce..4550125 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2025.1.2 +2025.1.3 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 7cec167..9cc066a 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2025.1.2 +version: 2025.1.3 From b0b19fee45a98514fbea149da5f467cadf64dd69 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:48:38 +0100 Subject: [PATCH 105/109] Fix missing `add_idf_sdkconfig_option` --- components/tx_ultimate_easy/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/tx_ultimate_easy/__init__.py b/components/tx_ultimate_easy/__init__.py index 7a7be12..f8ec729 100644 --- a/components/tx_ultimate_easy/__init__.py +++ b/components/tx_ultimate_easy/__init__.py @@ -2,6 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import uart +from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.const import ( CONF_ID, ) From 1cf6f60c78f198807490df2ced516b1097d42860 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Tue, 7 Jan 2025 07:49:22 +0000 Subject: [PATCH 106/109] Bump version to 2025.1.4 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 4550125..324444d 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2025.1.3 +2025.1.4 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 9cc066a..6762fa1 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2025.1.3 +version: 2025.1.4 From e944cd2c219771e3b4e4936a905b4a5e3d458fd0 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 15 Mar 2025 18:19:32 +0100 Subject: [PATCH 107/109] Remove reference to tj-actions Security reasons --- .github/workflows/validate_markdown.yml | 45 +++++++++++++++++-------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/.github/workflows/validate_markdown.yml b/.github/workflows/validate_markdown.yml index 1991d59..e72179a 100644 --- a/.github/workflows/validate_markdown.yml +++ b/.github/workflows/validate_markdown.yml @@ -17,23 +17,28 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@main + uses: actions/checkout@v4 with: - fetch-depth: '0' + fetch-depth: 0 # Ensures full commit history for diff - # https://github.com/marketplace/actions/markdownlint-cli2-action - name: Identify changed files - uses: tj-actions/changed-files@v41 id: changed-files - with: - files: '**/*.md' - separator: "," - # https://github.com/marketplace/actions/markdownlint-cli2-action + run: | + BASE=${{ github.event.before }} + HEAD=${{ github.sha }} + FILES=$(git diff --name-only $BASE $HEAD -- '**/*.md' | tr '\n' ',') + echo "changed_files=$FILES" >> $GITHUB_ENV + if [[ -n "$FILES" ]]; then + echo "any_changed=true" >> $GITHUB_ENV + else + echo "any_changed=false" >> $GITHUB_ENV + fi + - name: Markdown Lint uses: DavidAnson/markdownlint-cli2-action@v14 - if: steps.changed-files.outputs.any_changed == 'true' + if: env.any_changed == 'true' with: - globs: ${{ steps.changed-files.outputs.all_changed_files }} + globs: ${{ env.changed_files }} separator: "," config: '.rules/.markdownlint.jsonc' fix: true @@ -43,15 +48,27 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@main + uses: actions/checkout@v4 with: - fetch-depth: '0' + fetch-depth: 0 + + - name: Identify changed files + id: changed-files + run: | + BASE=${{ github.event.before }} + HEAD=${{ github.sha }} + FILES=$(git diff --name-only $BASE $HEAD -- '**/*.md' | tr '\n' ',') + echo "changed_files=$FILES" >> $GITHUB_ENV + if [[ -n "$FILES" ]]; then + echo "any_changed=true" >> $GITHUB_ENV + else + echo "any_changed=false" >> $GITHUB_ENV + fi - # https://github.com/gaurav-nelson/github-action-markdown-link-check - name: Markdown links uses: gaurav-nelson/github-action-markdown-link-check@v1 + if: env.any_changed == 'true' with: - # yamllint disable-line rule:truthy check-modified-files-only: yes config-file: '.rules/mlc_config.json' base-branch: 'main' From ace945a4ea1449c3feeb9119c3ed05adc11d9f63 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 15 Mar 2025 18:23:25 +0100 Subject: [PATCH 108/109] Update validate_yamllint.yml --- .github/workflows/validate_yamllint.yml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/validate_yamllint.yml b/.github/workflows/validate_yamllint.yml index 87a2c71..cf129a5 100644 --- a/.github/workflows/validate_yamllint.yml +++ b/.github/workflows/validate_yamllint.yml @@ -19,24 +19,29 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@main + uses: actions/checkout@v4 with: - fetch-depth: '0' + fetch-depth: 0 # Ensures full commit history for diff - name: Identify changed files - uses: tj-actions/changed-files@v41 id: changed-files - with: - files: '**/*.y*ml' - separator: "," + run: | + BASE=${{ github.event.before }} + HEAD=${{ github.sha }} + FILES=$(git diff --name-only $BASE $HEAD -- '**/*.yml' '**/*.yaml' | tr '\n' ',') + echo "changed_files=$FILES" >> $GITHUB_ENV + if [[ -n "$FILES" ]]; then + echo "any_changed=true" >> $GITHUB_ENV + else + echo "any_changed=false" >> $GITHUB_ENV + fi - name: Validate YAML - if: steps.changed-files.outputs.any_changed == 'true' + if: env.any_changed == 'true' run: | - IFS=',' read -ra FILES <<< "${{ steps.changed-files.outputs.all_changed_files }}" + IFS=',' read -ra FILES <<< "${{ env.changed_files }}" for file in "${FILES[@]}"; do - if [[ "$file" =~ ^*\.yaml$ ]] || \ - [[ "$file" =~ ^ESPHome/*\.yaml$ ]]; then + if [[ "$file" =~ ^.*\.yaml$ ]] || [[ "$file" =~ ^ESPHome/.*\.yaml$ ]]; then echo "Skipping $file" continue fi From be76ebd603e64a29b2ea949c15e3fbefe503a84e Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Fri, 21 Mar 2025 19:08:53 +0000 Subject: [PATCH 109/109] Bump version to 2025.3.1 [skip-versioning] --- versioning/VERSION | 2 +- versioning/VERSION_YAML | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/VERSION b/versioning/VERSION index 324444d..98c8c87 100644 --- a/versioning/VERSION +++ b/versioning/VERSION @@ -1 +1 @@ -2025.1.4 +2025.3.1 diff --git a/versioning/VERSION_YAML b/versioning/VERSION_YAML index 6762fa1..88f704d 100644 --- a/versioning/VERSION_YAML +++ b/versioning/VERSION_YAML @@ -1 +1 @@ -version: 2025.1.4 +version: 2025.3.1