gazoodle / gecko-home-assistant

Home Assistant integration for spas equipped with Gecko Alliance in.touch2 modules
MIT License
67 stars 22 forks source link

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

Open walterb65 opened 3 years ago

walterb65 commented 3 years ago

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

mikeboiko commented 3 years ago

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.

walterb65 commented 3 years ago

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.

mikeboiko commented 3 years ago

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.

gazoodle commented 3 years ago

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. 😀

mikeboiko commented 3 years ago

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!

RhinoRich commented 3 years ago

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

mikeboiko commented 3 years ago

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!

walterb65 commented 3 years ago

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

RhinoRich commented 3 years ago

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!

walterb65 commented 3 years ago

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:

picture-entity:

BR Walter

RhinoRich commented 3 years ago

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

Gaili commented 3 years ago

The state of my pumps are not reconized anymore!

RhinoRich commented 3 years ago

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.

TomK commented 3 years ago

@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

mikeboiko commented 3 years ago

@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.

TomK commented 3 years ago

@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

mikeboiko commented 3 years ago

@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!

TomK commented 3 years ago

@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);
mikeboiko commented 3 years ago

@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!

gazoodle commented 2 years ago

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 commented 2 years ago

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.