Dishwasher Status

UPDATE3: Fixed display for iOS devices

UPDATE2: Removed unecessary animation properties

UPDATE: Thanks to the wonderful heating widget of @Nico_R i finally understood how to create animations. This is getting a bit silly but since it also reduces the amount of code I now animated the opening and closing of the dishwasher. Be sure not to miss the magic moment :rofl:

Demo:

washing2

Iā€™m happy to present you the latest addition to my widget collection: The dishwasher widget. The widget is designed to work together with my washing machine widget and thus reuses parts of the code.

If you are already familiar with my washing machine widget then you already know how to use it. If not: Please see this thread for instructions: Washing machine status widget

Here you can see the widget in action (Running, Off, Finished washing):

dishwasher

Happy dishwashing!

Resources

Widget code:

uid: dishwasher_v6
tags: []
props:
  parameters:
    - description: Title of the card
      label: Title
      name: title
      required: false
      type: TEXT
    - description: The card footer
      label: Footer
      name: footer
      required: false
      type: TEXT
    - description: Header text above dishwasher
      label: Header
      name: header
      required: false
      type: TEXT
    - description: Expression that evaluates to minutes since the begin of washing
      label: Minutes running
      name: runtime
      required: true
      type: TEXT
    - description: Expression that evaluates to OFF, RUNNING or FINISHED
      label: State
      name: state
      required: true
      type: TEXT
  parameterGroups: []
timestamp: May 18, 2021, 12:42:12 PM
component: f7-card
config:
  title: =(props.title)
slots:
  default:
    - component: f7-card-content
      config:
        style:
          height: 175px
      slots:
        default:
          - component: f7-row
            config:
              class:
                - display-flex
                - justify-content-center
              style:
                width: 100%
            slots:
              default:
                - component: f7-col
                  config:
                    class:
                      - display-flex
                      - flex-direction-column
                      - align-items-center
                      - justify-content-space-evenly
                    style:
                      height: 100%
                  slots:
                    default:
                      - component: f7-block-header
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =props.header
                      - component: f7-block
                        config:
                          style:
                            height: 120px
                            width: 90px
                            border-radius: 2px 2px 4px 4px
                            background: rgba(255,255,255,1)
                            box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px
                          class:
                            - display-flex
                            - flex-direction-column
                            - align-items-center
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class:
                                  - display-flex
                                  - justify-content-flex-end
                                  - align-items-center
                                  - flex-shrink-0
                                  - no-margin
                                style:
                                  height: 23px
                                  width: 85px
                                  border-bottom: 1pt solid lightgray
                                  padding-right: 10px
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: circle_fill
                                      size: 10
                                      color: gray
                                  - component: f7-icon
                                    config:
                                      f7: circle_fill
                                      size: 10
                                      color: gray
                                  - component: f7-icon
                                    config:
                                      f7: '=props.state == "OFF" ? "circle_fill" : "sun_min"'
                                      size: 10
                                      style:
                                        color: '=props.state == "OFF" ? "gray" : "red"'
                            - component: f7-block
                              config:
                                class:
                                  - no-padding
                                style:
                                  height: calc(100% - 23px)
                                  width: 90%
                                  bottom: 0px
                                  position: absolute
                                  background: whitesmoke
                            - component: f7-block
                              config:
                                class:
                                  - display-flex
                                  - justify-content-center
                                  - align-items-center
                                style:
                                  position: absolute
                                  bottom: 0px
                                  left: 30%
                                  width: 40px
                                  height: 40px
                                  background: beige
                                  box-shadow: 0 0 16px 8px rgba(0, 0, 0, 0.10) inset
                                  border-radius: 50%
                                  transition: transform 0.6s
                                  transform: '=props.state == "FINISHED" ? "translate(-50%, -45px)" : "translate(-50%, 0)"'
                                  transform-origin: left center
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: circle
                                      size: 40
                                      style:
                                        color: beige
                            - component: f7-block
                              config:
                                class:
                                  - display-flex
                                  - justify-content-center
                                  - align-items-center
                                style:
                                  position: absolute
                                  bottom: 0px
                                  left: 50%
                                  width: 40px
                                  height: 40px
                                  background: beige
                                  box-shadow: 0 0 16px 8px rgba(0, 0, 0, 0.10) inset
                                  border-radius: 50%
                                  transition: transform 0.6s
                                  transform: '=props.state == "FINISHED" ? "translate(-50%, -47px)" : "translate(-50%, 0)"'
                                  transform-origin: left center
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: circle
                                      size: 40
                                      style:
                                        color: beige
                            - component: f7-block
                              config:
                                class:
                                  - display-flex
                                  - justify-content-center
                                  - align-items-center
                                style:
                                  position: absolute
                                  bottom: 0px
                                  left: 70%
                                  width: 40px
                                  height: 40px
                                  background: beige
                                  box-shadow: 0 0 16px 8px rgba(0, 0, 0, 0.10) inset
                                  border-radius: 50%
                                  transition: transform 0.6s
                                  transform: '=props.state == "FINISHED" ? "translate(-50%, -49px)" : "translate(-50%, 0)"'
                                  transform-origin: left center
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: circle
                                      size: 40
                                      style:
                                        color: beige
                            - component: f7-block
                              config:
                                style:
                                  height: 100%
                                  transform: translate3d(0, 0, 0)
                              slots:
                                default:
                                - component: f7-block
                                  config:
                                    class:
                                      - display-flex
                                      - flex-direction-column
                                      - justify-content-flex-start
                                      - align-items-center
                                    style:
                                      height: 100%
                                      width: 90px
                                      backgroundColor: '=props.state == "RUNNING" ? "white" : "whitesmoke"'
                                      transition: transform 0.6s
                                      transform: '=props.state != "RUNNING" ? "perspective(600px) rotateX(-55deg)" : "perspective(0px) rotateX(0deg)"'
                                      transform-origin: bottom center
                                      margin-top: auto
                                      box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 28px, rgba(0, 0, 0, 0.22) 0px 10px 10px
                                  slots:
                                    default:
                                      - component: f7-block
                                        config:
                                          style:
                                            height: 10px
                                            width: 90px
                                            position: absolute
                                            margin-top: -10px
                                            backgroundColor: white
                                            transition: transform 0.6s
                                            transform: '=props.state != "RUNNING" ? "perspective(600px) rotateX(35deg)" : "perspective(600px) rotateX(90deg)"'
                                            transform-origin: bottom center
                                            border-radius: 2px 2px 0px 0px
                                      - component: f7-block
                                        config:
                                          style:
                                            backgroundColor: gray
                                            margin-top: 10px
                                            height: 5px
                                            width: 5px
                                            border-radius: 2px 2px 0px 0px
                                      - component: f7-block
                                        config:
                                          class:
                                            - no-padding
                                          style:
                                            margin-top: 10px
                                            height: calc(100% - 40px)
                                            width: 100%
                                        slots:
                                          default:
                                            - component: f7-block
                                              config:
                                                colorTheme: lightblue
                                                class: custom-preloader-container-dummy
                                                style:
                                                  display: '=props.state == "RUNNING" ? "" : "none"'
                                                  margin: 0
                                                  padding: 0
                                                  --f7-preloader-size: 50px
                                                  --f7-preloader-color: var(--f7-theme-color)
                                                  position: absolute
                                                  left: 50%
                                                  top: 50%
                                                  transform: translate(-50%, -50%)
                                              slots:
                                                default:
                                                  - component: f7-block
                                                    config:
                                                      class: custom-preloader-dummy
                                                      style:
                                                        margin: 0
                                                        padding: 0
                                                        width: var(--f7-preloader-size)
                                                        height: var(--f7-preloader-size)
                                                    slots:
                                                      default:
                                                        - component: f7-block
                                                          config:
                                                            class: custom-preloader-inner-dummy
                                                            style:
                                                              margin: 0
                                                              padding: 0
                                                              position: absolute
                                                              left: 0
                                                              top: 0
                                                              width: 100%
                                                              height: 100%
                                                          slots:
                                                            default:
                                                              - component: f7-block
                                                                config:
                                                                  class: custom-preloader-inner-circle-dummy
                                                                  style:
                                                                    margin: 0
                                                                    padding: 0
                                                                    border-radius: 50%
                                                                    border: calc(var(--f7-preloader-size)/8) solid var(--f7-preloader-color)
                                                                    border-top-color: transparent
                                                                    box-sizing: border-box
                                                                    animation: aurora-preloader-rotate 1s linear infinite
                                                                    position: absolute
                                                                    left: 0
                                                                    top: 0
                                                                    width: 100%
                                                                    height: 100%
                                            - component: f7-block-header
                                              config:
                                                class:
                                                  - no-margin
                                                style:
                                                  position: absolute
                                                  top: 50%
                                                  left: 50%
                                                  transition: transform 0.6s
                                                  transform: '=props.state == "RUNNING" ? "scale(1, 1) translate(-50%, -50%)" : "scale(0, 0) translate(-50%, -50%)"'
                                                  transform-origin: left center
                                              slots:
                                                default:
                                                  - component: Label
                                                    config:
                                                      text: '=Math.floor(props.runtime / 60) + ":" + ((props.runtime % 60) < 10 ? ("0" + props.runtime % 60) : (props.runtime % 60))'
                                                      style:
                                                        color: black
    - component: f7-card-footer
      slots:
        default:
          - component: Label
            config:
              text: =props.footer
16 Likes

I realized that on Safari on an iPad the widget is not shown correctly when it has been added to a page but it looks fine in the editor also in Safariā€¦

Maybe someone can reproduce this!?

Hi @DrRSatzteil

nice widget and good work.
One statement from my side:

The animations doesnā€™t work because you cant define a animation in the yaml. All animations defined in the f7 core.
So in your code the parts like animation: open 0.3s linear both arenā€™t necessary because they doesnā€™t work.
The animation in your code is only based on the transition part.
You can delete the animation prop and the widget works as well. :wink:

(i hope my understanding of the current F7 hints is correct :smiley: )

best,
Nico

Hi Nico,

thank you for your explanation. I will get rid of this part then!

Even after my latest update the problem remains that in Safari the 3d rotated blocks are only shown in the editor but not on an actual pageā€¦ So I can see in the editor that the browser is capable of displaying it correctly but it just doesnā€™t on a pageā€¦ Couldnā€™t fix it with a higher z-index eitherā€¦

Which transformation you are referring to? Made a quick check on my iPad and everything looks clean at first glance.

Thanks for checking: the door of the dishwasher disappears on my iPad. But only when I add the widget to a page. In the editor it works just fine.

Even if I have no ad-hoc idea why it works in the editor and not on the pagesā€¦ but generally this might depend on the Safari version youā€™re using - older Safari versions might need a prefix. Try to add:

-webkit-transform: '=props.state != "RUNNING" ? "perspective(600px) rotateX(-55deg)" : "perspective(0px) rotateX(0deg)"'
transform-box: fill-box

The second property could be a soloution if your Safari version having problems with the interpretation of the transform-origin.

I tried the -webkit-transform lready but without success. It should not be necessary in my case anyway since my Safari is up to dateā€¦

I will try the transform-box suggestion later. Thank you!

Unfortunately the transform-box did not help either. I use this widget mainly on an android phone so this is not a really big issue. It is still weird and somehow unsatisfyingā€¦ Thank you for your valuable input anyway!

No problem, as it wasnā€™t very helpfull :stuck_out_tongue:
And yes, strange why it works for me then. The last idea I have, would be some kind of a caching problem, which is related to your testing while developing the widget, but just guessing here.

I think I can rule this out as well. The incognito mode does not help and I tried on another iPad yesterday where I had the same effect. Iā€™m also it of ideas hereā€¦ Thank you for your efforts with this issue

Hi.
First of all - thank you for sharing your widget. I think the community is really nice in openhab!
After i while a begin understanding how the code works. Just a Beginner - Sorry :slight_smile:

I have a smart dishwasher, so all items are available in items of bindings. So i have used this code:

Blockquote
- component: widget:dishwasher_v4
config:
runtime: =(items.SiemensGeschirrspuler_Remainingprogramtime.state)/60
title: GeschirrspĆ¼ler
state: =items.SiemensGeschirrspuler_PowerState.state
header: ā€œ=(items.SiemensGeschirrspuler_SelectedProgram != ā€œUNDEFā€ ) ? items.SiemensGeschirrspuler_SelectedProgram.state : ā€œā€ā€™ā€
footer: ā€œ=(items.SiemensGeschirrspuler_ActiveProgram.state != ā€œUNDEFā€ ) ? items.SiemensGeschirrspuler_ActiveProgram.state : ā€œā€ā€™ā€
Blockquote

Every works fine, but if the dishwasher is running, i doesnt see the time - it just see NaN:NaN

I am sure the code from you is working and the fault is mine - but i dont find it. :slight_smile: in your widgt i doesnt do anything on the runtime (i just have to delete Fininshed to OFF - couse my smart dishwasher brings other status back.

For better understanding: My dishwasher gives seconds back in the item SiemensGeschirrspuler_Remainingprogramtime. If i put this item to the header or the footer it gives me the seconds back.

Maybe any hints?

Hi Bernhard,

Maybe items.SiemensGeschirrspuler_Remainingprogramtime.state is a typed Number? Iā€™m not entirely sure if your expression is working like that then. Do you know that there is an expression tester you can reach via the developer tools (the link is not available on a mobile phone afaik)? I recommend to paste the code there. First without the ā€˜/60ā€™ and then add the ā€˜/60ā€™ to see if that works.

Hello.
I think its a Point Number:Date and Not a String. If i Type String i get a NULL Back. So dont think that this works. I will search the Expression Tester and will Test it. Withoit /60 it was the Same result. Thank you for your Help.

Ok. It is a Number:Time - semantic class Point Status
If i do in the Widgets Expression Tester : =items.SiemensGeschirrspuler_Remainingprogramtime.state) then it sends back the seconds - for example ā€œ10680 sā€. If i do /60 at the backwards it gets a NaN. So at the end of the code in the widget there is props.runtime / 60 - and thats why it becomes NaN in the Widget.

I dont know how i can resolve it this wayā€¦

Shouldnā€™t it work with?

=Math.round(items.SiemensGeschirrspuler_Remainingprogramtime.state.split(' ')[0] / 60) 
2 Likes

Even though I guess there is probably be a more elegant way you could try the following. I think that should work as well:

=items.SiemensGeschirrspuler_Remainingprogramtime.state.split(" ")[0]

1 Like

Oh you were faster :joy:

And your solution looks complete (compared to mine). You should try Rainerā€™s suggestion, Bernhard.

Thank you for the Support! It works fine!

In the meantime i have found an alternative to the running time. My dishwasher also delivers an percentage state, so i have changed the runtime piece of your code to:

slots:
default:
- component: Label
config:
text: =Math.floor(props.runtime) + ā€œ%ā€

in this case it shows me the percentage of the actual program like 75%.

Now, that the remaining time is shown, i dont need the percentage, but just for othersā€¦

Hi @Nico_R

This is weird: I realised that after I removed the animation properties from the preloader it goes wild on my mobile devices (Chrome on Android phone and iPad Safari): the preloader no longer is hidden/resized and rotates around a point close to the center of the preloader. Adding the animation tags again solved this. However in Chrome on Windows and Linux I do not observe this strange behaviour. Do you have any ideas why this happens?

1 Like