AmoebeLabs / swiss-army-knife-card

The versatile custom Swiss Army Knife card for Home Assistant allows you to create your unique visualization using several graphical tools, styling options and animations.
234 stars 19 forks source link

usersvg - png - animations not beingapplied #235

Open stinobook opened 1 year ago

stinobook commented 1 year ago

Bug report notice

Before you file a bug, make sure that you did not make a configuration mistake. The Swiss Army Knife in its current state does not yet have full configuration sanity checks!

I'm not sure actually

Swiss Army Knife version

image

Bug description

State animation not being applied to png usersvg. I have a robot vaccuum, and the rectex responds well to the animations (entity_index 0) for debugging purpose i also added a state with the text value of the entity_index 1. when aplying the style directly (without animations) it works. once i try to apply it through animations it doesn't respond. current life span of main brush is 0.54% which is rounded to 1 with the decimals:0. since i thought maybe it was an issue with the comma. ive tried adding ' brackets around the state value: card isnt drawn anymore at all (no error card, just invisible) adding ' over operator: doesn't do anything adding entity_index in the state animation: nothing since its a percentage, maybe sak treated it as a percentage, so i used 0.10, 0.20, 10% 20% as states as well: also nothing i wanted to wait for the update to see if that might have a fix but still the same issue. so if you see anything thats wrong with the code or if it is an actual bug, please enlighten me.

To Reproduce

card code:

              - type: 'custom:swiss-army-knife-card'
                aspectratio: 1/1
                entities:
                  - entity: vacuum.marie_jose
                  - entity: sensor.marie_jose_life_span_brush
                    decimals: 0
                  - entity: sensor.marie_jose_life_span_side_brush
                    decimals: 0
                  - entity: sensor.marie_jose_life_span_filter
                    decimals: 0
                layout:
                  styles:
                    card:
                      background: linear-gradient(135deg, rgba(254,100,146,1) 0%, rgba(242,151,94,1) 100%)
                      border: none
                      box-shadow: none
                  toolsets:
                    - toolset: background
                      position:
                       cx: 50
                       cy: 50
                      tools:
                        - type: rectex
                          position:
                            cx: 50
                            cy: 50
                            width: 100
                            height: 100
                          entity_index: 0
                          styles:
                            rectex:
                              fill: rgba(0,0,0,0)
                          user_actions:
                            tap_action:
                              haptic: light
                              actions:
                                - action: fire-dom-event
                                  browser_mod:
                                          --not relevant, removed-
                          animations:
                            - state: 'cleaning'
                              styles:
                                rectex:
                                  fill: rgba(0,0,0,0)
                                  transition: fill 0.5s linear
                            - state: 'docked'
                              styles:
                                rectex:
                                  fill: rgba(97, 69, 71, 1)
                                  transition: fill 0.5s linear
                            - state: 'docked'
                              operator: '!='
                              styles:
                                rectex:
                                  fill: rgba(97, 69, 71, 1)
                                  transition: fill 0.5s linear
                        - type: state
                          position:
                            cx: 50
                            cy: 15
                          entity_index: 1
                          styles:
                            state:
                              font-size: 10em
                        - type: usersvg
                          position:
                            cx: 75
                            cy: 15
                            height: 30
                            width: 30
                          entity_index: 1
                          style: 'images'
                          images:
                            - default: /local/images/main-brush.png
                          animations:
                            - state: 10
                              operator: <=
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: 20
                              operator: <=
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0.5
                            - state: 20
                              operator: >
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0
                        - type: usersvg
                          position:
                            cx: 75
                            cy: 35
                            height: 30
                            width: 30
                          entity_index: 2
                          style: 'images'
                          images:
                            - default: /local/images/side-brush.png
                          animations:
                            - state: 10
                              operator: <=
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: 20
                              operator: <=
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0.5
                            - state: 20
                              operator: >
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0
                        - type: usersvg
                          position:
                            cx: 75
                            cy: 55
                            height: 30
                            width: 30
                          entity_index: 3
                          style: 'images'
                          images:
                            - default: /local/images/filter.png
                          animations:
                            - state: 10
                              operator: <=
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: 20
                              operator: <=
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0.5
                            - state: 20
                              operator: >
                              styles:
                                usersvg:
                                  filter: unset
                                  opactiy: 0
                        - type: icon
                          position:
                            cx: 25
                            cy: 25
                            align: start
                            icon_size: 45
                          entity_index: 0
                          styles:
                            icon:
                              fill: var(--primary-text-color)
                              color: var(--primary-text-color)
                              pointer-events: none
                          animations:
                            - state: unknown
                              icon: mdi:lan-disconnect
                              styles:
                                icon:
                                  fill: var(--paper-toggle-button-checked-button-color)
                            - state: error
                              icon: mdi:alert
                              styles:
                                icon:
                                  fill: var(--paper-toggle-button-checked-button-color)
                            - state: '-ua-'
                              icon: mdi:lan-disconnect
                              styles:
                                icon:
                                  fill: var(--paper-toggle-button-checked-button-color)
                            - state: '-ua-'
                              operator: '!='
                              styles:
                                icon:
                                  fill: var(--primary-text-color)
                        - type: name
                          position:
                            cx: 10
                            cy: 80
                          entity_index: 0
                          styles:
                            name:
                              text-anchor: start
                              font-size: 14em
                              font-weight: 500
                              pointer-events: none
                        - type: state
                          position:
                            cx: 10
                            cy: 92
                          entity_index: 0
                          styles:
                            state:
                              text-anchor: start
                              font-size: 9em
                              opacity: 0.5

Expected behavior

change appearance on svg based on state.

Screenshots

card example: image

stinobook commented 1 year ago

I think there might be something more going on. my TRV card is also bugged out now with the new 2.5.1 update:

it's showing as if its on: image and the radiator icon is missing: image (dont mind the missing humidity, there isn't one in that room, different type of card/thermostat, different detection to see if its on)

for these i had this code/animations: (same for the rectex)


      - type: icon
        position:
          cx: 33
          cy: 77
          align: center
          icon_size: 15
        entity_index: '[[var_entity_index1]]'
        animations:
          - state: '1'
            icon: mdi:radiator
            operator: '>='
            styles:
              icon:
                fill: rgba(125, 0, 0, 1)
                color: rgba(125, 0, 0, 1)
          - state: '0'
            icon: mdi:radiator-disabled
            styles:
              icon:
                fill: var(--primary-text-color)
                color: var(--primary-text-color)

which uses this sensor: image

and it now seems to have an issue using that readout since the 2.5 update. coincidentally its 2 sensors now which have a percentage measurement that arent working. PS: the OP card wasn't working before either, but now since the TRV card is also bugged it might be something else..

this is the brush sensor: image

stinobook commented 1 year ago

And the thermostat that was working also joined now.. (the one in the previous post) image

AmoebeLabs commented 1 year ago

I will have a look!

Regarding the icons: These are now fully compliant with how the newest version of Home Assistant Core is translating them: and YES, that is different than how the previous version of SAK did that.

My energy switches used to show the "power" icon, but now show the "switch" icon for that specific entity.

Take a look at this card: on the left the on/off switching, and on the right the energy consumption. Both used to display the "power" icon.

image

But if you look at the history for the on/off switch, you can see that HA also uses the "switch" icon, and as SAK now uses the logic from HA, SAK also displays the "switch" icon instead of the "power" icon.

image

I already specified - in many cases - the icon I wanted in the entities config.

This is how my boiler example displays:

image

image

However, if I omit some of the icons: image

HA, and thus SAK now uses the "boiler" icon for all these entities:

image

The same happened to my default HA entities card for my boiler, showing only "boiler" icons:

image

It should look like this (now with fixed icons specified):

image

The animations are still working: image

image

So, if you can compare with what HA is showing and/or specify your own fixed icons, that should fix your icons.

AmoebeLabs commented 1 year ago

As for one of your problems, I just realized that the state 'unavailable' did not work previously, as it was internally translated to '-ua-'.

With the refactoring of the state machine, SAK now is able to use the 'unavailable' state, so I think if you replace '-ua-' with 'unavailable', your animation should work again...

image

As you can see below, the 'unavailable' state is now also localized correctly:

image

That was one of the reasons to support 'unavailable', as the HA localization engine requires this.

My SAKE9 example dashboard is still working with icon and card color changes depending on the state. I did not have to make changes for those cards:

No movement: image

Movement: image

stinobook commented 1 year ago

Thanks for looking into this. Im going to split this up a bit: vacuum card: the -ua- was a part i didnt even notice yet since i havent had it disconnect, so i applied that fix. the issue here is the usersvg part not applying the style with regards to the state (the usersvgs that use the png files) image

thermostat card (the one in my last post) this only fails if i call the card via the template. if i copy all the code from the template and just apply it normally it just works.. so issue might be in the template engine now ? image

TRV card: also removed one from the template to test, since the templates don't update as fast as the main ui yaml. here sadly it still malfunctions. trying to get the radiator icon to show to test the state animations: image

so this part of my code (the 1 and 0 is for the TRV, on and off is for the other thermostat card)

          - state: '1'
            icon: mdi:radiator
            operator: '>='
            styles:
              icon:
                fill: rgba(125, 0, 0, 1)
                color: rgba(125, 0, 0, 1)
          - state: '0'
            icon: mdi:radiator-disabled
            styles:
              icon:
                fill: var(--primary-text-color)
                color: var(--primary-text-color)
          - state: 'on'
            icon: mdi:radiator
            styles:
              icon:
                fill: rgba(125, 0, 0, 1)
                color: rgba(125, 0, 0, 1)
          - state: 'off'
            icon: mdi:radiator-disabled
            styles:
              icon:
                fill: var(--primary-text-color)
                color: var(--primary-text-color)

things i've tried so far, since current state of that sensor is 0.0: removed all animations except for the state 0 tried following values: 0 '0' 0% '0%' 0.0 '0.0'

yet it doesnt display the icon in any case.

since the icons get set through the animations, the 'switch' icon you mention above of the thermostat card is automatically fixed when the animation works. When i remove the card and apply it to the thermostat card it works as expected: ignores 0 and 1 state and applies on/off state. strangely enough it doesn't work when its in the template. So far what i can see is the animation state has issues with percentage sensors,

-- update while writing this post, i had another idea --

i added this code to the icon part:


                          icon: mdi:radiator-disabled

image

so basically like i mentioned in another issue where the tool didnt work if the label wasn't defined, here it seems now you MUST set a basic state before animations can be applied. for the rectex animation: the 'base' state was rgba(0,0,0,0) which i had to replace with rgba(97, 69, 71, 1).

adding said changes and making it call through the template also fixes this issue for the thermostat card, it can be called again through the template and works how it should.

since this post is getting a bit long, this is a fix for thermostat card and trv card. now to tackle the vacuum card.

AmoebeLabs commented 1 year ago

About percentages. If you use 'format: brightness', that should be replaced with 'convert: brightness'.

But other than that, the animation engine hasn't changed, nor has the template engine.

But you might have stumbled on an edge case, as I always define 'default' styles in my cards, so I can see if there is an unhandled state for the animations like 'undefined' or 'unavailable'.

The switch tool for instance has its thumb in the middle by default as long as there is no 'on' or 'off' state received.

If your problem and the solution is clear, I can add that to the documentation about animations!

stinobook commented 1 year ago

Well, sadly my ideas aren't working for the vacuum card.

so far i'm at this: image

where i added a default style for the usersvg. which does get applied. however the animation now with the 'is not' 'test' makes the card stop drawing itself completely, while in my opinion that should give me an absolute 'true' value..

going this far: changed entity index to 0 which i know works on the rectex, using the same state image

also does NOT let the card draw itself.. strange stuff..

moving the enity index in the animation lets the card draw again but not apply the animation: image

AmoebeLabs commented 1 year ago

Do you see errors in the console of the browser? As it seems if nothing draws, some error is detected.

My pollen and AQI test cards still work, so your card does other things than I have tested.

stinobook commented 1 year ago

console when card draws: image

console when it doesnt: image

AmoebeLabs commented 1 year ago

Ok. That explains at least that SAK won't do what it should do.

What version of HA core are you running?

stinobook commented 1 year ago

image latest everything :)

AmoebeLabs commented 1 year ago

Ok. I'm still running 2023.5.x

The crash with the (reading 'lastIndexOf') points to the fact that the animation returns an image that is not in the images list, so you get the 'cannot read properties of undefined' error.

The lowercase errors will likely prevent the state handler from doing its job. The animation engine is part of that state handler, so also won't do what it should do.

stinobook commented 1 year ago

Breakthrough! thinking about my 'default' state on the other cards, thought about adding a default IMAGE to the animations: image

image

and this works. so what im thinking is it wants to apply the state but it doesn't know what image it has to apply it on!

stinobook commented 1 year ago

Hope this helps you with the developement of the card :) so the 'simple' fix was having to add a default image to animations on usersvgs (mabye only in case they use png? )

you can close this if you want for me. depending if you see an issue to fix in your code or just add it to the docs

image

Final (working) code:


                        - type: usersvg
                          position:
                            cx: 75
                            cy: 15
                            height: 30
                            width: 30
                          style: 'images'
                          entity_index: 1
                          styles:
                            usersvg:
                              opacity: 0
                          images:
                            - default: /local/images/main-brush.png
                          animations:
                            - state: '1'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: '10'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0.5
                            - state: '10'
                              operator: '>'
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0
                        - type: usersvg
                          position:
                            cx: 75
                            cy: 35
                            height: 30
                            width: 30
                          entity_index: 2
                          style: 'images'
                          styles:
                            usersvg:
                              opacity: 0
                          images:
                            - default: /local/images/side-brush.png
                          animations:
                            - state: '1'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: '10'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0.5
                            - state: '10'
                              operator: '>'
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0
                        - type: usersvg
                          position:
                            cx: 75
                            cy: 55
                            height: 30
                            width: 30
                          entity_index: 3
                          style: 'images'
                          styles:
                            usersvg:
                              opacity: 0
                          images:
                            - default: /local/images/filter.png
                          animations:
                            - state: '1'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  filter: invert(50%) sepia(17%) saturate(5187%) hue-rotate(321deg) brightness(94%) contrast(89%)
                                  opacity: 1
                            - state: '10'
                              operator: '<='
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0.5
                            - state: '10'
                              operator: '>'
                              image: default
                              styles:
                                usersvg:
                                  opacity: 0
AmoebeLabs commented 1 year ago

Great!

I now think I know what's going on: as of v2.5.1, the 'undefined' state is processed through the pipeline as it now has become a valid state, including localization.

Previously, an 'undefined' state was filtered very early in the state handler.

Now I think the usersvg tool tries to apply styles and more to an 'undefined' state, which it previously never received, and thus never applied styles to that state.

By setting the 'default' image, you always have a valid state, as the image is the resulting state for the usersvg tool. The animations engine can't guess of course the right image with an 'undefined' state.

I just checked all my examples, and they either use a list of images, or use a Javascript template to determine the image, which ALWAYS returns a 'default' image. Hence those always work!

image

stinobook commented 1 year ago

It all seems so logical once you find out what causes it :)

PS: console is pretty clean as well now: image

AmoebeLabs commented 1 year ago

Hope this helps you with the developement of the card :) so the 'simple' fix was having to add a default image to animations on usersvgs (mabye only in case they use png? )

you can close this if you want for me. depending if you see an issue to fix in your code or just add it to the docs

I will keep it open for now, to add validation in the code, and put it in the documentation.

It all seems so logical once you find out what causes it :)

Yup. Most of the bugs are very logical once you find the problem. This one never was a problem because the 'undefined' state was filtered. So the omission of the default image was never a problem!

Thanx for debugging 😄