gecko-home-assistant icon indicating copy to clipboard operation
gecko-home-assistant copied to clipboard

Since update to latest version I'm not able to turn on/off my pumps

Open walterb65 opened this issue 3 years ago • 21 comments

Since the change of pumps from switch to fan my pumps can not be turned on/of. The state is recognized. Enabled debug do not show any errors. Switching back to 0.0.6 with geckolib 0.3.19 work again. I habe no vario speed pumps

walterb65 avatar Jul 17 '21 17:07 walterb65

image Did you try changing the Preset Mode setting? Toggling the pump on/off does nothing for me now, but changing the Preset Mode allows me to control my pumps.

mikeboiko avatar Jul 18 '21 14:07 mikeboiko

you are right, changing preset mode work for me too. Anywas it would be great to have On/Off switch working for none vario speed pumps. I know that I wrap this setting to a switch in HA but i prefer to have it oob.

walterb65 avatar Jul 18 '21 14:07 walterb65

I think we should be able to solve this by getting a better lovelace component for a fan. I haven't gotten a chance to test any yet, but a quick google search led me to one example: https://community.home-assistant.io/t/lovelace-custom-fan-card-example/68318/68

I'll keep you posted when I find a good solution.

mikeboiko avatar Jul 18 '21 14:07 mikeboiko

I noticed this after I merged the variable speed fan stuff in, and so it’s on my schedule to fix. The switch ought to toggle between HI and OFF for single speed pumps … indeed the options ought to be limited to that. Investigation is proceeding. 😀

gazoodle avatar Jul 18 '21 15:07 gazoodle

I noticed this after I merged the variable speed fan stuff in, and so it’s on my schedule to fix. The switch ought to toggle between HI and OFF for single speed pumps … indeed the options ought to be limited to that. Investigation is proceeding. grinning

@gazoodle, you're the man!

mikeboiko avatar Jul 18 '21 15:07 mikeboiko

I had the same. I use a graphic of my tub with pump icons and changed the entities for them to input_booleans which trigger automations with service calls to set the fan presents (OFF or HI). Needs two automations (on to off and off to on) for each pump, so it's clumsy but it does work image

RhinoRich avatar Jul 20 '21 07:07 RhinoRich

I noticed this after I merged the variable speed fan stuff in, and so it’s on my schedule to fix. The switch ought to toggle between HI and OFF for single speed pumps … indeed the options ought to be limited to that. Investigation is proceeding. grinning

EDIT: Ignore my bug below. I fixed it and updated the code. The button clicks work now.


@gazoodle, I followed this lovelace custom fan example and got it somewhat functioning. I want to share with you in case you find this useful and want to roll out to the rest of the users. I could always make a separate Github repo for the custom card if we decide to proceed down this path.

I am able to successfully see the preset_mode states for my pump. image

However, when I click on OFF/LO/HIGH, I get the following error:

home-assistant     | Traceback (most recent call last):
home-assistant     |   File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
home-assistant     |     await hass.services.async_call(
home-assistant     |   File "/usr/src/homeassistant/homeassistant/core.py", line 1491, in async_call
home-assistant     |     task.result()
home-assistant     |   File "/usr/src/homeassistant/homeassistant/core.py", line 1526, in _execute_service
home-assistant     |     await handler.job.target(service_call)
home-assistant     |   File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
home-assistant     |     await self.hass.helpers.service.entity_service_call(
home-assistant     |   File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 658, in entity_service_call
home-assistant     |     future.result()  # pop exception if have
home-assistant     |   File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 811, in async_request_call
home-assistant     |     await coro
home-assistant     |   File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 695, in _handle_entity_call
home-assistant     |     await result
home-assistant     |   File "/config/custom_components/gecko/fan.py", line 33, in async_set_preset_mode
home-assistant     |     self._automation_entity.set_mode(preset_mode)
home-assistant     |   File "/usr/local/lib/python3.9/site-packages/geckolib/automation/pump.py", line 38, in set_mode
home-assistant     |     logger.exception("Exception handling setting %s=%s", key, val)
home-assistant     | NameError: name 'key' is not defined

I added a custom lovelace card www/fan-card.js:

class CustomFanCard extends Polymer.Element {
  static get template() {
    return Polymer.html`
            <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
            <style>
                .flex-container {
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
                @keyframes mdc-ripple-fg-radius-in{from{animation-timing-function:cubic-bezier(0.4, 0, 0.2, 1);transform:translate(var(--mdc-ripple-fg-translate-start, 0)) scale(1)}to{transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}}@keyframes mdc-ripple-fg-opacity-in{from{animation-timing-function:linear;opacity:0}to{opacity:var(--mdc-ripple-fg-opacity, 0)}}@keyframes mdc-ripple-fg-opacity-out{from{animation-timing-function:linear;opacity:var(--mdc-ripple-fg-opacity, 0)}to{opacity:0}}.mdc-ripple-surface--test-edge-var-bug{--mdc-ripple-surface-test-edge-var: 1px solid #000;visibility:hidden}.mdc-ripple-surface--test-edge-var-bug::before{border:var(--mdc-ripple-surface-test-edge-var)}.mdc-button{font-family:Roboto,sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:.875rem;line-height:2.25rem;font-weight:500;letter-spacing:.0892857143em;text-decoration:none;text-transform:uppercase;--mdc-ripple-fg-size: 0;--mdc-ripple-left: 0;--mdc-ripple-top: 0;--mdc-ripple-fg-scale: 1;--mdc-ripple-fg-translate-end: 0;--mdc-ripple-fg-translate-start: 0;-webkit-tap-highlight-color:rgba(0,0,0,0);will-change:transform,opacity;padding:0 8px 0 8px;display:inline-flex;position:relative;align-items:center;justify-content:center;box-sizing:border-box;min-width:64px;height:36px;border:none;outline:none;line-height:inherit;user-select:none;-webkit-appearance:none;overflow:hidden;vertical-align:middle;border-radius:4px}.mdc-button::before,.mdc-button::after{position:absolute;border-radius:50%;opacity:0;pointer-events:none;content:""}.mdc-button::before{transition:opacity 15ms linear,background-color 15ms linear;z-index:1}.mdc-button.mdc-ripple-upgraded::before{transform:scale(var(--mdc-ripple-fg-scale, 1))}.mdc-button.mdc-ripple-upgraded::after{top:0;left:0;transform:scale(0);transform-origin:center center}.mdc-button.mdc-ripple-upgraded--unbounded::after{top:var(--mdc-ripple-top, 0);left:var(--mdc-ripple-left, 0)}.mdc-button.mdc-ripple-upgraded--foreground-activation::after{animation:225ms mdc-ripple-fg-radius-in forwards,75ms mdc-ripple-fg-opacity-in forwards}.mdc-button.mdc-ripple-upgraded--foreground-deactivation::after{animation:150ms mdc-ripple-fg-opacity-out;transform:translate(var(--mdc-ripple-fg-translate-end, 0)) scale(var(--mdc-ripple-fg-scale, 1))}.mdc-button::before,.mdc-button::after{top:calc(50% - 100%);left:calc(50% - 100%);width:200%;height:200%}.mdc-button.mdc-ripple-upgraded::after{width:var(--mdc-ripple-fg-size, 100%);height:var(--mdc-ripple-fg-size, 100%)}.mdc-button::-moz-focus-inner{padding:0;border:0}.mdc-button:active{outline:none}.mdc-button:hover{cursor:pointer}.mdc-button:disabled{background-color:transparent;color:rgba(0,0,0,.37);cursor:default;pointer-events:none}.mdc-button.mdc-button--dense{border-radius:4px}.mdc-button:not(:disabled){background-color:transparent}.mdc-button:not(:disabled){color:#6200ee;color:var(--mdc-theme-primary, #6200ee)}.mdc-button::before,.mdc-button::after{background-color:#6200ee}@supports not (-ms-ime-align: auto){.mdc-button::before,.mdc-button::after{background-color:var(--mdc-theme-primary, #6200ee)}}.mdc-button:hover::before{opacity:.04}.mdc-button:not(.mdc-ripple-upgraded):focus::before,.mdc-button.mdc-ripple-upgraded--background-focused::before{transition-duration:75ms;opacity:.12}.mdc-button:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-button:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:.16}.mdc-button.mdc-ripple-upgraded{--mdc-ripple-fg-opacity: 0.16}.mdc-button .mdc-button__icon{margin-left:0;margin-right:8px;display:inline-block;width:18px;height:18px;font-size:18px;vertical-align:top}[dir=rtl] .mdc-button .mdc-button__icon,.mdc-button .mdc-button__icon[dir=rtl]{margin-left:8px;margin-right:0}.mdc-button svg.mdc-button__icon{fill:currentColor}.mdc-button--raised .mdc-button__icon,.mdc-button--unelevated .mdc-button__icon,.mdc-button--outlined .mdc-button__icon{margin-left:-4px;margin-right:8px}[dir=rtl] .mdc-button--raised .mdc-button__icon,.mdc-button--raised .mdc-button__icon[dir=rtl],[dir=rtl] .mdc-button--unelevated .mdc-button__icon,.mdc-button--unelevated .mdc-button__icon[dir=rtl],[dir=rtl] .mdc-button--outlined .mdc-button__icon,.mdc-button--outlined .mdc-button__icon[dir=rtl]{margin-left:8px;margin-right:-4px}.mdc-button--raised,.mdc-button--unelevated{padding:0 16px 0 16px}.mdc-button--raised:disabled,.mdc-button--unelevated:disabled{background-color:rgba(0,0,0,.12);color:rgba(0,0,0,.37)}.mdc-button--raised:not(:disabled),.mdc-button--unelevated:not(:disabled){background-color:#6200ee}@supports not (-ms-ime-align: auto){.mdc-button--raised:not(:disabled),.mdc-button--unelevated:not(:disabled){background-color:var(--mdc-theme-primary, #6200ee)}}.mdc-button--raised:not(:disabled),.mdc-button--unelevated:not(:disabled){color:#fff;color:var(--mdc-theme-on-primary, #fff)}.mdc-button--raised::before,.mdc-button--raised::after,.mdc-button--unelevated::before,.mdc-button--unelevated::after{background-color:#fff}@supports not (-ms-ime-align: auto){.mdc-button--raised::before,.mdc-button--raised::after,.mdc-button--unelevated::before,.mdc-button--unelevated::after{background-color:var(--mdc-theme-on-primary, #fff)}}.mdc-button--raised:hover::before,.mdc-button--unelevated:hover::before{opacity:.08}.mdc-button--raised:not(.mdc-ripple-upgraded):focus::before,.mdc-button--raised.mdc-ripple-upgraded--background-focused::before,.mdc-button--unelevated:not(.mdc-ripple-upgraded):focus::before,.mdc-button--unelevated.mdc-ripple-upgraded--background-focused::before{transition-duration:75ms;opacity:.24}.mdc-button--raised:not(.mdc-ripple-upgraded)::after,.mdc-button--unelevated:not(.mdc-ripple-upgraded)::after{transition:opacity 150ms linear}.mdc-button--raised:not(.mdc-ripple-upgraded):active::after,.mdc-button--unelevated:not(.mdc-ripple-upgraded):active::after{transition-duration:75ms;opacity:.32}.mdc-button--raised.mdc-ripple-upgraded,.mdc-button--unelevated.mdc-ripple-upgraded{--mdc-ripple-fg-opacity: 0.32}.mdc-button--raised{box-shadow:0px 3px 1px -2px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 1px 5px 0px rgba(0,0,0,.12);transition:box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1)}.mdc-button--raised:hover,.mdc-button--raised:focus{box-shadow:0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0,0,0,.12)}.mdc-button--raised:active{box-shadow:0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0,0,0,.12)}.mdc-button--raised:disabled{box-shadow:0px 0px 0px 0px rgba(0, 0, 0, 0.2),0px 0px 0px 0px rgba(0, 0, 0, 0.14),0px 0px 0px 0px rgba(0,0,0,.12)}.mdc-button--outlined{border-style:solid;padding:0 14px 0 14px;border-width:2px}.mdc-button--outlined:disabled{border-color:rgba(0,0,0,.37)}.mdc-button--outlined:not(:disabled){border-color:#6200ee;border-color:var(--mdc-theme-primary, #6200ee)}.mdc-button--dense{height:32px;font-size:.8125rem}.material-icons{font-family:var(--mdc-icon-font, "Material Icons");font-weight:normal;font-style:normal;font-size:var(--mdc-icon-size, 24px);line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;-webkit-font-feature-settings:"liga";-webkit-font-smoothing:antialiased}:host{display:inline-flex;outline:none}.mdc-button{flex:1}
                :host {
                    display: inherit;
                }
                .preset-modes button:host {
                    display: inline-flex;
                    outline: none;
                }
                .preset-modes button {
                    min-width: 34px !important;
                    width: 34px;
                }
                /*ha-entity-toggle {
                    margin-left: 16px;
                }*/
            </style>
            <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
                <div class='flex-container' on-click="_stopPropagation">
                    <div class="preset-modes">
                        <button
                            class="mdc-button mdc-button--raised mdc-ripple-upgraded"
                            toggles name="OFF"
                            on-click='_setPresetMode'
                            disabled='[[_isOff]]'>
                            <span class="mdc-button__label">OFF</span>
                        </button>
                        <button
                            class="mdc-button mdc-button--raised mdc-ripple-upgraded"
                            toggles name="LO"
                            on-click='_setPresetMode'
                            disabled='[[_isLowMode]]'>
                            <span class="mdc-button__label">LO</span>
                        </button>
                        <button
                            class="mdc-button mdc-button--raised mdc-ripple-upgraded"
                            toggles name="HI"
                            on-click='_setPresetMode'
                            disabled='[[_isHighMode]]'>
                            <span class="mdc-button__label">HI</span>
                        </button>
                    </div>
                    <!--<ha-entity-toggle hass="[[hass]]" state-obj="[[_stateObj]]"></ha-entity-toggle>-->
                </div>
            </hui-generic-entity-row>
        `;
  }

  static get properties() {
    return {
      hass: {
        type: Object,
        observer: "_hassChanged",
      },
      _config: Object,
      _stateObj: Object,
      _isOff: Boolean,
      _isLowMode: Boolean,
      _isHighMode: Boolean,
    };
  }

  setConfig(config) {
    this._config = config;
  }

  _hassChanged(hass) {
    const config = this._config;
    const stateObj = hass.states[config.entity];

    let preset_mode;
    if (stateObj && stateObj.attributes) {
      preset_mode = stateObj.attributes.preset_mode || "OFF";
    }

    this.setProperties({
      _stateObj: stateObj,
      _isOff: preset_mode === "OFF",
      _isLowMode: preset_mode == "LO",
      _isHighMode: preset_mode === "HI",
    });
  }

  _stopPropagation(e) {
    e.stopPropagation();
  }

  _setPresetMode(e) {
    const preset_mode = e.currentTarget.getAttribute("name");
    this.hass.callService("fan", "set_preset_mode", {
      entity_id: this._config.entity,
      preset_mode: preset_mode,
    });
  }
}

customElements.define("custom-fan-card", CustomFanCard);

I added the resource in configration.yaml

lovelace:
  mode: yaml
  resources:
    - url: /local/fan-card.js?v=0.0.1
      type: module

I referenced custom-fan-card in ui-lovelace.yaml:

- type: entities
  title: Controls
  show_header_toggle: false
  entities:
    - entity: climate.my_spa_heater
      secondary_info: last-changed
    - entity: fan.my_spa_pump_1
      type: custom:custom-fan-card
      secondary_info: last-changed
      icon: mdi:fan

Any tips on how to fix the set_preset_mode service call buttons?

Thanks!

mikeboiko avatar Jul 20 '21 19:07 mikeboiko

I haven't tried the fan card. I'm using button-card. This card can be customized with JS.

image

  - entity: fan.linde_und_walter_s_whirli_pump_1
    tap_action:
      action: call-service
      service: fan.set_preset_mode
      service_data:
        entity_id: fan.linde_und_walter_s_whirli_pump_1
        preset_mode: |
          [[[
           if (entity.state == "off")
            return "HI";
           else
            return "OFF";
          ]]]
      show_name: true
    styles:
      card:
        - height: 155px
        - font-size: 14px
      icon:
        - height: 30px
    type: custom:button-card

This works for me

walterb65 avatar Jul 20 '21 19:07 walterb65

I haven't tried the fan card. I'm using button-card. This card can be customized with JS.

image

  - entity: fan.linde_und_walter_s_whirli_pump_1
    tap_action:
      action: call-service
      service: fan.set_preset_mode
      service_data:
        entity_id: fan.linde_und_walter_s_whirli_pump_1
        preset_mode: |
          [[[
           if (entity.state == "off")
            return "HI";
           else
            return "OFF";
          ]]]
      show_name: true
    styles:
      card:
        - height: 155px
        - font-size: 14px
      icon:
        - height: 30px
    type: custom:button-card

This works for me

That's what I needed. Thank you!

RhinoRich avatar Jul 20 '21 20:07 RhinoRich

Picture-elements does not support javascript.

You can setup a switch in your configuration.yaml and toggle the switch with an state-icon.

Configuration.yaml

switch:

  • platform: template switches: jet1: friendly_name: 'Spa Jet1' turn_on: service: fan.set_preset_mode data: preset_mode: 'HI' entity_id: fan.ducky_tub_pump_1 turn_off: service: fan.set_preset_mode data: preset_mode: 'OFF' entity_id: fan.ducky_tub_pump_1

picture-entity:

  • type: state-icon tap_action: action: toggle entity: switch.jet1 show_name: true icon: mdi:pump name: Jet 1 style: transform: translate(-50%, -50%) scale(6,6) '--paper-item-icon-color': white left: 6% top: 60%

BR Walter

walterb65 avatar Jul 21 '21 19:07 walterb65

Hi Walter. Actually in the end I was able to integrate your custom:button-cards into the picture elements card. Thank you!

type: picture-elements
elements:
  - type: state-label
    entity: sensor.spa_temperature
    style:
      top: 50%
      left: 48%
      transform: translate(-50%,-50%) scale(2,2)
      opacity: 65%
      color: cyan
  - type: custom:button-card
    entity: fan.ducky_tub_pump_1
    style:
      transform: translate(-50%, -50%) scale(.8,.8)
      left: 9%
      top: 63%
      opacity: 70%
    size: 60px
    show_name: false
    action: toggle
    tap_action:
      action: call-service
      service: fan.set_preset_mode
      service_data:
        entity_id: fan.ducky_tub_pump_1
        preset_mode: |
          [[[
           if (entity.state == 'off')
            return 'HI';
           else
            return 'OFF';
          ]]]

image

RhinoRich avatar Jul 22 '21 08:07 RhinoRich

The state of my pumps are not reconized anymore!

Gaili avatar Jul 27 '21 04:07 Gaili

The state of my pumps are not reconized anymore!

Your pumps would have been switch entities in HA. The component now provides them as fans. Please see above.

RhinoRich avatar Jul 27 '21 07:07 RhinoRich

@mikeboiko thanks for your solution for the entity rows. I like the simplicity of it. Your code block seems to be a bit broken though, looks like the whole file has been pasted again into the middle of the block.

I might have to tweak the buttons slightly as the active one has come out quite dark. image

however, i'm having a problem with it atm. will be having a look into this later on. image

TomK avatar Aug 13 '21 12:08 TomK

@mikeboiko thanks for your solution for the entity rows. I like the simplicity of it. Your code block seems to be a bit broken though, looks like the whole file has been pasted again into the middle of the block.

I might have to tweak the buttons slightly as the active one has come out quite dark. image

however, i'm having a problem with it atm. will be having a look into this later on. image

Oops, I somehow gobbled the code when I copy/pasted it. Try the updated snippet. I like the idea of changing the colors. They look fine in light mode, but unusable in dark mode. I just found this template in a forum, so I didn't spend any time on customizing the colors. Let me know if you make some improvements to it.

mikeboiko avatar Aug 13 '21 14:08 mikeboiko

@mikeboiko i've removed most of the CSS, now looks like this. Should work with themes. image

<style>
  :host {
      display: inherit;
  }
  .flex-container {
      display: flex;
      justify-content: center;
      align-items: center;
  }
  .preset-modes button:host {
      display: inline-flex;
      outline: none;
  }
  .mdc-button:disabled {
    background: var(--primary-color);
    color: var(--primary-text-color);
  }
</style>

Light mode looks inverted, i'll make some adjustments later image EDIT: i must not have refreshed properly. it's acceptable! image

TomK avatar Aug 13 '21 14:08 TomK

@mikeboiko i've removed most of the CSS, now looks like this. Should work with themes. image

<style>
  :host {
      display: inherit;
  }
  .flex-container {
      display: flex;
      justify-content: center;
      align-items: center;
  }
  .preset-modes button:host {
      display: inline-flex;
      outline: none;
  }
  .mdc-button:disabled {
    background: var(--primary-color);
    color: var(--primary-text-color);
  }
</style>

Light mode looks inverted, i'll make some adjustments later image

Nice, I like the simplicity of it!

mikeboiko avatar Aug 13 '21 14:08 mikeboiko

@mikeboiko i've cleaned this up now, and fixed the pump issues. The buttons are now dynamic based on the available preset modes reported by the entity.

class CustomFanCard extends Polymer.Element {
  static get template() {
    return Polymer.html`
              <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
              <style>
                  :host {
                      display: inherit;
                  }
                  .flex-container {
                      display: flex;
                      justify-content: space-between;
                      align-items: right;
                  }
                  .mdc-button {
                      display: inline-flex;
                      outline: none;
                      margin-left: 3px;
                  }
                  .mdc-button:disabled {
                    background: var(--primary-color);
                    color: var(--primary-text-color);
                  }
              </style>
              <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
                  <div class="flex-container">
                      <dom-repeat items="{{_modes}}">
                        <template>
                          <button
                              class="mdc-button mdc-button--raised mdc-ripple-upgraded"
                              toggles name="[[item]]"
                              on-click='_setPresetMode'
                              disabled='[[_isSelected(item,_mode)]]'>
                              <span class="mdc-button__label">[[item]]</span>
                          </button>
                        </template>
                      </dom-repeat>
                  </div>
              </hui-generic-entity-row>
          `;
  }

  static get properties() {
    return {
      hass: {
        type: Object,
        observer: "_hassChanged",
      },
      _config: Object,
      _mode: String,
      _modes: Array,
    };
  }

  setConfig(config) {
    this._config = config;
  }

  _hassChanged(hass) {
    const config = this._config;
    const stateObj = hass.states[config.entity];

    this.setProperties({
      _stateObj: stateObj,
      _mode: (stateObj && stateObj.attributes && stateObj.attributes.preset_mode) || "OFF",
      _modes: stateObj.attributes.preset_modes || ["OFF"],
    });
  }

  _setPresetMode(e) {
    const preset_mode = e.currentTarget.getAttribute("name");

    this.hass.callService("fan", "set_preset_mode", {
      entity_id: this._config.entity,
      preset_mode: preset_mode,
    });
  }

  _isSelected(test, expect) {
    return test === expect;
  }
}

customElements.define("custom-fan-card", CustomFanCard);

TomK avatar Aug 13 '21 16:08 TomK

@mikeboiko i've cleaned this up now, and fixed the pump issues. The buttons are now dynamic based on the available preset modes reported by the entity.

class CustomFanCard extends Polymer.Element {
  static get template() {
    return Polymer.html`
              <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
              <style>
                  :host {
                      display: inherit;
                  }
                  .flex-container {
                      display: flex;
                      justify-content: space-between;
                      align-items: right;
                  }
                  .mdc-button {
                      display: inline-flex;
                      outline: none;
                      margin-left: 3px;
                  }
                  .mdc-button:disabled {
                    background: var(--primary-color);
                    color: var(--primary-text-color);
                  }
              </style>
              <hui-generic-entity-row hass="[[hass]]" config="[[_config]]">
                  <div class="flex-container">
                      <dom-repeat items="{{_modes}}">
                        <template>
                          <button
                              class="mdc-button mdc-button--raised mdc-ripple-upgraded"
                              toggles name="[[item]]"
                              on-click='_setPresetMode'
                              disabled='[[_isSelected(item,_mode)]]'>
                              <span class="mdc-button__label">[[item]]</span>
                          </button>
                        </template>
                      </dom-repeat>
                  </div>
              </hui-generic-entity-row>
          `;
  }

  static get properties() {
    return {
      hass: {
        type: Object,
        observer: "_hassChanged",
      },
      _config: Object,
      _mode: String,
      _modes: Array,
    };
  }

  setConfig(config) {
    this._config = config;
  }

  _hassChanged(hass) {
    const config = this._config;
    const stateObj = hass.states[config.entity];

    this.setProperties({
      _stateObj: stateObj,
      _mode: (stateObj && stateObj.attributes && stateObj.attributes.preset_mode) || "OFF",
      _modes: stateObj.attributes.preset_modes || ["OFF"],
    });
  }

  _setPresetMode(e) {
    const preset_mode = e.currentTarget.getAttribute("name");

    this.hass.callService("fan", "set_preset_mode", {
      entity_id: this._config.entity,
      preset_mode: preset_mode,
    });
  }

  _isSelected(test, expect) {
    return test === expect;
  }
}

customElements.define("custom-fan-card", CustomFanCard);

Nice, I like that! I noticed some of your screenshots still show the old style formatting. Are you revving up the version of your custom resource? For example, every time I make a change to fan-card.js, I change the version number in configration.yaml as such:

lovelace: # {{{1
  # Increment ?v=xxx to force browser to reload resource
  mode: yaml
  resources:
    - url: /local/fan-card.js?v=0.0.5
      type: module

I experienced some weird issues with the old javascript code remaining after I reloaded resources. After reading the documentation, it seems that changing the version forces a full reload in the browser. Thought this tip might be helpful to you and others!

mikeboiko avatar Aug 13 '21 19:08 mikeboiko

There is some nice work here guys! I'm going to leave this issue open so that I can return to it later to review in more detail what's going on, but v0.0.8 has changed the way the pump switch works so that the default UI will go from "OFF" to "HI" and back when the switch is operated.

gazoodle avatar Feb 04 '22 21:02 gazoodle

Also noticed that you folk were also getting a "key" not defined error ... irritatingly that was a syntax fault in the exception handler ... this ought to be fixed now and while it won't deal with the underlying problem, you ought to be able to see what the code was complaining about.

gazoodle avatar Feb 08 '22 13:02 gazoodle