Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4 Relays version #26

Open
umbex opened this issue Dec 3, 2023 · 11 comments
Open

4 Relays version #26

umbex opened this issue Dec 3, 2023 · 11 comments

Comments

@umbex
Copy link

umbex commented Dec 3, 2023

Hello,
thanks for the great work!

I'm tinkering with the 120-4 Relays EU version, and I figured out to enable the 4th channel touch on the yaml.

FYI, touch positions are mapped as follows:
Touch 1: pos 1,2
Touch 2: pos 3,4,5
Touch 3: pos 6,7,8
Touch 4: pos 9,10

LEDS are 32.
Top side: from 31 to 8
Right side: from 9 to 14
Bottom side: from 15 to 24
Left side: from 25 to 30

Having four buttons, the mapping of scripts with button_left, middle, right will need a renaming maybe.
It will be great if you will like to support this device version.
All the best

@Jetro97
Copy link

Jetro97 commented Dec 13, 2023

Same here,

I'm available to help supporting this version

@iUnstable0
Copy link

same. also @umbex thanks for providing the positions n the led ill try maybe editing and if it works might create a PR

@iUnstable0
Copy link

@umbex for the leds the orientation u mean when mounting it portrait? or landscape? if you get what i mean 😅

@iUnstable0
Copy link

iUnstable0 commented Dec 25, 2023

@umbex this is useful
#15 (comment)

I edited it and added support for 4 relays also changed a couple of things to match my needs
this is the yaml
variant.c4.yaml

script:
  - id: do_nighttime_mode_active
    then:
      - lambda: |-
          ESP_LOGD("script.do_nighttime_mode_active", "Nighttime mode activated...");

          float red = ${nt_exp_red};
          float green = ${nt_exp_green};
          float blue = ${nt_exp_blue};
          float bright = ${nt_exp_bright};

          float s_red = ${nt_exp_s_red};
          float s_green = ${nt_exp_s_green};
          float s_blue = ${nt_exp_s_blue};
          float s_bright = ${nt_exp_s_bright};

          ESP_LOGD("script.do_nighttime_mode_active", "Setting TEMPLATE(s) => R: %f G: %f B: %f BR: %f", red, green, blue, bright);

          id(leds_sw_left).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_bright).set_transition_length(0).perform();
          id(leds_sw_right).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_bright).set_transition_length(0).perform();

          id(figure_out_which_partition_to_light).execute(1);
          id(figure_out_which_partition_to_light).execute(2);
          id(figure_out_which_partition_to_light).execute(3);
          id(figure_out_which_partition_to_light).execute(4);

  - id: do_daytime_mode_active
    then:
      - lambda: |-
          ESP_LOGD("script.do_daytime_mode_active", "Daytime mode activated...");

          float red = ${dt_exp_red};
          float green = ${dt_exp_green};
          float blue = ${dt_exp_blue};
          float bright = ${dt_exp_bright};

          float s_red = ${nt_exp_s_red};
          float s_green = ${nt_exp_s_green};
          float s_blue = ${nt_exp_s_blue};
          float s_bright = ${nt_exp_s_bright};

          ESP_LOGD("script.do_daytime_mode_active", "Setting TEMPLATE(s) => R: %f G: %f B: %f BR: %f", red, green, blue, bright);

          id(leds_sw_left).turn_off().set_rgb( s_red, s_green, s_blue ).set_brightness(s_bright).set_transition_length(0).perform();
          id(leds_sw_right).turn_off().set_rgb( s_red, s_green, s_blue ).set_brightness(s_bright).set_transition_length(0).perform();

          id(figure_out_which_partition_to_light).execute(1);
          id(figure_out_which_partition_to_light).execute(2);
          id(figure_out_which_partition_to_light).execute(3);
          id(figure_out_which_partition_to_light).execute(4);

  - id: figure_out_which_partition_to_light
    mode: single
    parameters:
      output_num: int
    then:
      - lambda: |-
          auto TAG = "script.figure_out_which_partition_to_light";
          // We don't know WHICH partition light to pull RGB/BR from, but regardless we do need place to store....
          float red, green, blue, br;

          float s_red = ${nt_exp_s_red};
          float s_green = ${nt_exp_s_green};
          float s_blue = ${nt_exp_s_blue};
          float s_br = ${nt_exp_s_bright};

          ESP_LOGD(TAG, "Trigger was output %d", output_num);

          switch (output_num) {
            case 1:
                // Output 1 is left button, so we want to light the top partition
                id(template_light_1).current_values_as_rgb(&red, &green, &blue);
                id(template_light_1).current_values_as_brightness(&br);
                ESP_LOGD(TAG, "Light State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);

                // Will be either just .state for entities that have bool on/off properties or something like
                //  .current_values.is_on() for entities that don't.
                if(id(out_1).${out_1_state_exp}) {
                  ESP_LOGD(TAG, "out_1: ON, setting left side ON");

                  ESP_LOGD(TAG, "glbl_normal_regime_mode_is_nighttime: %d", id(glbl_normal_regime_mode_is_nighttime));

                  // If night mode is active, we dont turn off but instead change the color to match the exp_s values (left and right side of the switches for night light)
                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_1_bottom).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_1_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }

                  id(leds_button_1_top).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                } else {
                  ESP_LOGD(TAG, "out_1: OFF, setting right side ON");

                  id(leds_button_1_bottom).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();

                  ESP_LOGD(TAG, "glbl_normal_regime_mode_is_nighttime: %d", id(glbl_normal_regime_mode_is_nighttime));

                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_1_top).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_1_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }
                }
                break;
            case 2:
                id(template_light_2).current_values_as_rgb(&red, &green, &blue);
                id(template_light_2).current_values_as_brightness(&br);
                
                ESP_LOGD(TAG, "Light State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);

                // The C++ code we call changes based on which type of output out_2 is
                if(id(out_2).${out_2_state_exp}) {
                  ESP_LOGD(TAG, "out_2: ON, setting left side ON");
                  
                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_2_bottom).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_2_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }
                  
                  id(leds_button_2_top).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                } else {
                  ESP_LOGD(TAG, "out_2: OFF, setting right side ON");

                  id(leds_button_2_bottom).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();

                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_2_top).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_2_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }
                }
                break;
            case 3:
                id(template_light_3).current_values_as_rgb(&red, &green, &blue);
                id(template_light_3).current_values_as_brightness(&br);

                ESP_LOGD(TAG, "Light State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);

                if(id(out_3).${out_3_state_exp}) {
                  ESP_LOGD(TAG, "out_3: ON, setting left side ON");

                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_3_bottom).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_3_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }

                  id(leds_button_3_top).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                } else {
                  ESP_LOGD(TAG, "out_3: OFF, setting right side ON");

                  id(leds_button_3_bottom).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();

                  if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                    id(leds_button_3_top).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                  } else {
                    id(leds_button_3_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  }
                }
                break;
              case 4:
                  id(template_light_4).current_values_as_rgb(&red, &green, &blue);
                  id(template_light_4).current_values_as_brightness(&br);

                  ESP_LOGD(TAG, "Light State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);

                  if(id(out_4).${out_4_state_exp}) {
                    ESP_LOGD(TAG, "out_4: ON, setting left side ON");

                    if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                      id(leds_button_4_bottom).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                    } else {
                      id(leds_button_4_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                    }

                    id(leds_button_4_top).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                  } else {
                    ESP_LOGD(TAG, "out_4: OFF, setting right side ON");

                    id(leds_button_4_bottom).turn_on().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();

                    if ( id(glbl_normal_regime_mode_is_nighttime) ) {
                      id(leds_button_4_top).turn_on().set_rgb( s_red, s_green, s_blue ).set_brightness(s_br).set_transition_length(0).perform();
                    } else {
                      id(leds_button_4_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
                    }
                  }
                  break;
              default:
                ESP_LOGE(TAG, "Unknown output number: %d", output_num);
                return;
            }

  # Called on boot or any time we're transitioning from mood-light to a "normal" mode
  - id: resume_normal_regime_for_leds
    mode: single
    # When resuming normal regime, figure out which color scheme we should be using and then run the "figure out which partition to light" script for each output
    then:
      # TODO: SUN HORIZON
      # - script.execute:
      #     id: figure_out_normal_regime_mode
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 1
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 2
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 3
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 4

##
# See the LEDs section of readme.md
# There are 10 LEDs on each side, we have 3 groups which means we'll need 4 "buffers"
# 10 - 4 = 6 and 6/3 is 2 so we'll use 2 leds per partition
##
light:
  - name: "Left"
    platform: partition
    id: leds_sw_left
    segments:
      - id: leds_all
        from: 25
        to: 30
      - id: leds_all
        from: 0
        to: 1
      - id: leds_all
        from: 3
        to: 4
      - id: leds_all
        from: 6
        to: 7

    effects:
      - addressable_scan:
          name: "Scan"
      - addressable_rainbow:
          name: "Rainbow"
          speed: 10
          width: 20

  - name: "Right"
    platform: partition
    id: leds_sw_right
    segments:
      - id: leds_all
        from: 9
        to: 14
      - id: leds_all
        from: 16
        to: 17
      - id: leds_all
        from: 19
        to: 20
      - id: leds_all
        from: 22
        to: 23

    effects:
      - addressable_scan:
          name: "Scan"
      - addressable_rainbow:
          name: "Rainbow"
          speed: 10
          width: 20
          
  - name: "Button Left Top (internal)"
    platform: partition
    id: leds_button_1_top
    internal: true
    segments:
      - id: leds_all
        from: 31
        to: 31

  - name: "Button Left Bottom (internal)"
    platform: partition
    id: leds_button_1_bottom
    internal: true
    segments:
      - id: leds_all
        from: 24
        to: 24

  - name: "Button Middle Left Top (internal)"
    platform: partition
    id: leds_button_2_top
    internal: true
    # segments: [3]
    segments:
      - id: leds_all
        from: 2
        to: 2

  - name: "Button Middle Left Bottom (internal)"
    platform: partition
    id: leds_button_2_bottom
    internal: true
    # segments: [22]
    segments:
      - id: leds_all
        from: 21
        to: 21

  - name: "Button Middle Right Top (internal)"
    platform: partition
    id: leds_button_3_top
    internal: true
    # segments: [6]
    segments:
      - id: leds_all
        from: 5
        to: 5

  - name: "Button Middle Right Bottom (internal)"
    platform: partition
    id: leds_button_3_bottom
    internal: true
    # segments: [19]
    segments:
      - id: leds_all
        from: 18
        to: 18

  - name: "Button Right Top (internal)"
    platform: partition
    id: leds_button_4_top
    internal: true
    # segments: [9]
    segments:
      - id: leds_all
        from: 8
        to: 8

  - name: "Button Right Bottom (internal)"
    platform: partition
    id: leds_button_4_bottom
    internal: true
    # segments: [16]
    segments:
      - id: leds_all
        from: 15
        to: 15

  # Expose a "template" light entity to HA.
  # Use this to "wrap" the partition lights and pass through values to them.
  # See readme.md for more info
  - platform: custom
    lambda: |-
      // Sign of life
      ESP_LOGD("light.template_light", "Alive!");

      auto template_light_1 = new TemplateLight();
      App.register_component(template_light_1);

      auto template_light_2 = new TemplateLight();
      App.register_component(template_light_2);

      auto template_light_3 = new TemplateLight();
      App.register_component(template_light_3);

      auto template_light_4 = new TemplateLight();
      App.register_component(template_light_4);

      return {template_light_1, template_light_2, template_light_3, template_light_4};

    lights:
      - name: "Indicator 1"
        id: template_light_1
        # Expose to HA, under config section
        internal: false
        entity_category: config

        # Template light should restore to last state / ON at boot
        restore_mode: RESTORE_AND_ON
        # We do not bother with gamma correction here, we want to keep the values as unadulterated as possible as this is JUST a pass through
        # The actual light(s) that we pass values to will handle gamma correction (if configured)
        gamma_correct: 0.0
        # Likewise, we do not want to do any smoothing here, we want to pass the values through as quickly as possible
        default_transition_length: 0s

        # In testing, I can't get the (gamma corrected...) partition light(s) to turn on at all below ~20%.
        # Not clear _why_ this is (too dim to see?) but it's a problem because there's nothing preventing you from setting a brightness of < 20% in HA.
        # HA thinks that the light is on, but it's not actually on.
        # Ideally i'd be able to set min_brightness here like I can with other types of light in ESPHome, but I can't.
        # More than likely i'll need to implement this myself in the template_light.h file.
        ##
        # We need to link our state to the actual partition lights... which is not as straightforward as expected.
        # After a lot of trial/error, this is the least janky method I could come up with.
        ##
        # Because we have a transition length of 0, the on_state hook really shouldn't be called more than 2x
        # Once as soon as any command is received; it'll print the state we're about to move away from
        # Once as soon as we've reached the  commanded state that was just received; it'll print the state we're at / should match what HA commanded.
        # However, the on_state call is STILL needed because a light that is on full red and then given a command to go to full purple will not pass through
        #   on/off state.
        ##
        on_turn_on:
          - lambda: |-
              // Get user requested RGB values and pass them through to the partition lights
              float red, green, blue, br;
              id(template_light_1).current_values_as_rgb(&red, &green, &blue);
              id(template_light_1).current_values_as_brightness(&br);

              // Pass through should happen ONLY in the on_state and on_turn_off hooks so just log here
              // Since we have ZERO gamma correction, the values here should _match_ the ones set in HA
              // They'll just be normalized though. So HA sends red: 255, here, we get 1.0
              ESP_LOGD("template_light_1.on_turn_on", "ON_TURN_ON => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

        on_turn_off:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_1).current_values_as_rgb(&red, &green, &blue);
              id(template_light_1).current_values_as_brightness(&br);
              // OFF means OFF so both partitions should be off
              ESP_LOGD("template_light_1.on_turn_off", "TURN OFF");
              id(leds_button_1_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
              id(leds_button_1_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();              

        on_state:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_1).current_values_as_rgb(&red, &green, &blue);
              id(template_light_1).current_values_as_brightness(&br);
              ESP_LOGD("template_light_1.on_state", "State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

          # Figure out which partition light to light up now that we have an updated state
          - script.execute:
              id: figure_out_which_partition_to_light
              # Output 1 = top
              output_num: 1

      - name: "Indicator 2"
        id: template_light_2
        internal: false
        entity_category: config
        restore_mode: RESTORE_AND_ON
        gamma_correct: 0.0
        default_transition_length: 0s

        on_turn_on:
          - lambda: |-
              // Get user requested RGB values and pass them through to the partition lights
              float red, green, blue, br;
              id(template_light_2).current_values_as_rgb(&red, &green, &blue);
              id(template_light_2).current_values_as_brightness(&br);

              // Pass through should happen ONLY in the on_state and on_turn_off hooks so just log here
              // Since we have ZERO gamma correction, the values here should _match_ the ones set in HA
              // They'll just be normalized though. So HA sends red: 255, here, we get 1.0
              ESP_LOGD("template_light_2.on_turn_on", "ON_TURN_ON => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

        on_turn_off:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_2).current_values_as_rgb(&red, &green, &blue);
              id(template_light_2).current_values_as_brightness(&br);
              // OFF means OFF so both partitions should be off
              ESP_LOGD("template_light_2.on_turn_off", "TURN OFF");
              id(leds_button_2_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
              id(leds_button_2_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();              

        on_state:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_2).current_values_as_rgb(&red, &green, &blue);
              id(template_light_2).current_values_as_brightness(&br);
              ESP_LOGD("template_light_2.on_state", "State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

          - script.execute:
              id: figure_out_which_partition_to_light
              # Output 2 = middle on 3c version
              output_num: 2

      - name: "Indicator 3"
        id: template_light_3
        internal: false
        entity_category: config
        restore_mode: RESTORE_AND_ON
        gamma_correct: 0.0
        default_transition_length: 0s

        on_turn_on:
          - lambda: |-
              // Get user requested RGB values and pass them through to the partition lights
              float red, green, blue, br;
              id(template_light_3).current_values_as_rgb(&red, &green, &blue);
              id(template_light_3).current_values_as_brightness(&br);

              // Pass through should happen ONLY in the on_state and on_turn_off hooks so just log here
              // Since we have ZERO gamma correction, the values here should _match_ the ones set in HA
              // They'll just be normalized though. So HA sends red: 255, here, we get 1.0
              ESP_LOGD("template_light_3.on_turn_on", "ON_TURN_ON => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

        on_turn_off:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_3).current_values_as_rgb(&red, &green, &blue);
              id(template_light_3).current_values_as_brightness(&br);
              // OFF means OFF so both partitions should be off
              ESP_LOGD("template_light_3.on_turn_off", "TURN OFF");
              id(leds_button_3_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
              id(leds_button_3_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();              

        on_state:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_3).current_values_as_rgb(&red, &green, &blue);
              id(template_light_3).current_values_as_brightness(&br);
              ESP_LOGD("template_light_3.on_state", "State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

          - script.execute:
              id: figure_out_which_partition_to_light
              output_num: 3

      - name: "Indicator 4"
        id: template_light_4
        internal: false
        entity_category: config
        restore_mode: RESTORE_AND_ON
        gamma_correct: 0.0
        default_transition_length: 0s

        on_turn_on:
          - lambda: |-
              // Get user requested RGB values and pass them through to the partition lights
              float red, green, blue, br;
              id(template_light_4).current_values_as_rgb(&red, &green, &blue);
              id(template_light_4).current_values_as_brightness(&br);

              // Pass through should happen ONLY in the on_state and on_turn_off hooks so just log here
              // Since we have ZERO gamma correction, the values here should _match_ the ones set in HA
              // They'll just be normalized though. So HA sends red: 255, here, we get 1.0
              ESP_LOGD("template_light_4.on_turn_on", "ON_TURN_ON => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);              

        on_turn_off:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_4).current_values_as_rgb(&red, &green, &blue);
              id(template_light_4).current_values_as_brightness(&br);
              // OFF means OFF so both partitions should be off
              ESP_LOGD("template_light_4.on_turn_off", "TURN OFF");
              id(leds_button_4_top).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();
              id(leds_button_4_bottom).turn_off().set_rgb( red, green, blue ).set_brightness(br).set_transition_length(0).perform();              

        on_state:
          - lambda: |-
              // Get template RGB values
              float red, green, blue, br;
              id(template_light_4).current_values_as_rgb(&red, &green, &blue);
              id(template_light_4).current_values_as_brightness(&br);
              ESP_LOGD("template_light_4.on_state", "State => R: %f, G: %f, B: %f BR: %f", red, green, blue, br);

# Set up the gpio outputs for the relays
output:
  - id: relay_1
    platform: gpio
    pin: GPIO18

  - id: relay_2
    platform: gpio
    pin: GPIO17

  - id: relay_3
    platform: gpio
    pin: GPIO27

  - id: relay_4
    platform: gpio
    pin: GPIO23

testswitch.yaml (snippet)

packages:
  common: !include packages/base.yaml

  # 3 relay version
  output: !include
    file: packages/variant.c4.yaml
    vars:
      # Relay 1,3 are wired up to lights
      # out_1_state_exp: "state"
      out_1_state_exp: "current_values.is_on()"
      # out_2_state_exp: "state"
      out_2_state_exp: "current_values.is_on()"
      # out_3_state_exp: "state"
      out_3_state_exp: "current_values.is_on()"
      # out_4_state_exp: "state"
      out_4_state_exp: "current_values.is_on()"

# Customize what each of the three relays do
light:
  # Relay 1 and 2 are the fan/light combo
  - name: Left Light
    id: out_1
    platform: binary
    output: relay_1
    restore_mode: RESTORE_DEFAULT_OFF

    # When changing between states, we need to update the partition light(s)
    on_turn_on:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 1

    on_turn_off:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 1

  # Main overhead light
  - name: Middle Left Light
    id: out_2
    platform: binary
    output: relay_2
    restore_mode: RESTORE_DEFAULT_OFF

    on_turn_on:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 2

    on_turn_off:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 2

  # Main overhead light
  - name: Middle Right Light
    id: out_3
    platform: binary
    output: relay_3
    restore_mode: RESTORE_DEFAULT_OFF

    on_turn_on:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 3

    on_turn_off:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 3

  - name: Right Light
    id: out_4
    platform: binary
    output: relay_4
    restore_mode: RESTORE_DEFAULT_OFF

    on_turn_on:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 4

    on_turn_off:
      - script.execute:
          id: figure_out_which_partition_to_light
          output_num: 4

tx_ultimate_touch:
  id: tx_touch
  uart: uart_touch

  on_press:
    # Let the user know we've registered the touch
    - script.execute: buzz_default
    # Like "traditional" switches, we act as soon as pressed and do not wait for "release"
    # Unless user has disabled touch input processing
    - lambda: >
        ESP_LOGD("tx_ultimate_touch.on_press", "Touch Position: %d / State: %d", touch.x, touch.state);

        if (!id(glbl_sw_touch_enable)) {
          ESP_LOGD("tx_ultimate_touch.on_press", "Touch is disabled, ignoring");
          return;
        }

        // 4 ch version means we split the touch surface into 4 equal size zones
        // 0-2, 3-5, 6-8, 9-11
        // There's nothing stopping you from creating unequal sized zones if desired!
        /////////////////////////////////
        // The if/else pattern is extended or shortened depending on the number of relays
        // In addition to modifying the if/else pattern, you'll need to update the code that
        //    checks the state of each output.
        // I wish ESPHome would have a more homogenous API for this since there IS a homogenous
        //  API for calling the turn_on/turn_off methods!
        /////////////////////////////////

        if (touch.x <= 2) {
          ESP_LOGD("tx_ultimate_touch.on_press", "Toggle 1");
          if(id(out_1).current_values.is_on() ) {
            id(out_1).turn_off().perform();
          } else {
            id(out_1).turn_on().perform();
          }
        } else if (touch.x <= 5) {
          ESP_LOGD("tx_ultimate_touch.on_press", "Toggle 2");
          if(id(out_2).current_values.is_on() ) {
            id(out_2).turn_off().perform();
          } else {
            id(out_2).turn_on().perform();
          }
        } else if (touch.x <= 8) {
          ESP_LOGD("tx_ultimate_touch.on_press", "Toggle 3");
          if(id(out_3).current_values.is_on() ) {
            id(out_3).turn_off().perform();
          } else {
            id(out_3).turn_on().perform();
          }
        } else {
          ESP_LOGD("tx_ultimate_touch.on_press", "Toggle 4");
          if(id(out_4).current_values.is_on() ) {
            id(out_4).turn_off().perform();
          } else {
            id(out_4).turn_on().perform();
          }
        }     

(thanks to @kquinsland)

@m4dm4xi
Copy link

m4dm4xi commented Jan 31, 2024

Hello, thanks for the great work!

I'm tinkering with the 120-4 Relays EU version, and I figured out to enable the 4th channel touch on the yaml.

FYI, touch positions are mapped as follows: Touch 1: pos 1,2 Touch 2: pos 3,4,5 Touch 3: pos 6,7,8 Touch 4: pos 9,10

LEDS are 32. Top side: from 31 to 8 Right side: from 9 to 14 Bottom side: from 15 to 24 Left side: from 25 to 30

Having four buttons, the mapping of scripts with button_left, middle, right will need a renaming maybe. It will be great if you will like to support this device version. All the best

Have you found a properly working solution?

@SebTM
Copy link
Contributor

SebTM commented Feb 29, 2024

Hey, I'm looking forward to get one of the 4-gang version, is there any chance this component will add support for the 4-gang version as well? ✌🏻

@madmagic007
Copy link

Im looking for support for the 4 gang version as well. can only get 3 relays to work

@Elkropac
Copy link

Hi, what needs to be done to support 4gang EU version? I was looking at the @iUnstable0 snippet, but it seems like it's something completely different

@iUnstable0
Copy link

not sure what i did wrong but using my snippet completely bricks the device 😭

i was testing my firmware and bricked all of em so i switched to sonoff m5

@Elkropac
Copy link

i have modified tx_local yaml for 4 relays. I will create PR tomorrow.

@Elkropac
Copy link

@iUnstable0 you cannot even flash them via cable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants