Dishwasher Status

@DrRSatzteil & @Nico_R - I’m also experiencing this too (weird animation effects on mobile); haven’t been able to pin it down yet…

@Bernhard_R & @Nico_R - great Widget here! I also have a ‘smart’ Samsung dishwasher, but as I’m using openHAB didn’t want to fuss with adding a SmartThings hub into the mix just for polling the dishwasher via their 3rd party proprietary Cloud APIs. Sooo, I ended up hacking this together instead:

  • Discovered the Dishwashers IP address from my routers DHCP server.
  • Added it as a ‘Thing’ via the openHAB Network Binding.
  • Created a new string ‘Item’ to monitor its state in the format this Widget expects (i.e. ONLINE = RUNNING, OFFLINE = FINISHED).
  • Created a new ‘Item’ for ‘minutes’. While I cant directly instrument the dishwasher this way to get the minutes remaining in the cycle, I’d be fine with assuming it will take 2 hours on average to complete. Haven’t wired in the logic on this just yet to display the countdown time…
  • Created 2 rules. One for Dishwasher-ON and Dishwasher-OFF:

RUNNING:

triggers:
  - id: "1"
    configuration:
      itemName: DW_Online
      state: ON
      previousState: OFF
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: DW_State
      state: RUNNING
    type: core.ItemStateUpdateAction

OFF

triggers:
  - id: "1"
    configuration:
      itemName: DW_Online
      state: OFF
      previousState: ON
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      itemName: DW_State
      state: FINISHED
    type: core.ItemStateUpdateAction

And then finally rewired the Widget code to work with the new OH items:

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
    - context: item
      description: Expression that evaluates to minutes since the begin of washing
      label: Minutes running
      name: runtime
      required: true
      type: TEXT
    - context: item
      description: Expression that evaluates to OFF, RUNNING or FINISHED
      label: State
      name: state
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Mar 12, 2021, 9:56:07 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: '=items[props.state].state == "OFF" ? "circle_fill" : "sun_min"'
                                      size: 10
                                      style:
                                        color: '=items[props.state].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: '=items[props.state].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: '=items[props.state].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: '=items[props.state].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:
                                class:
                                  - display-flex
                                  - flex-direction-column
                                  - justify-content-flex-start
                                  - align-items-center
                                style:
                                  height: 100%
                                  width: 90px
                                  backgroundColor: '=items[props.state].state == "RUNNING" ? "white" : "whitesmoke"'
                                  transition: transform 0.6s
                                  transform: '=items[props.state].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: '=items[props.state].state != "RUNNING" ? "perspective(600px) rotateX(35deg)" : "perspective(600px) rotateX(90deg)"'
                                        transform-origin: bottom center
                                        border-radius: 2px
                                  - 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-preloader
                                          config:
                                            size: 50
                                            colorTheme: lightblue
                                            style:
                                              position: absolute
                                              top: 50%
                                              left: 50%
                                              transition: transform 0.6s
                                              transform: '=items[props.state].state == "RUNNING" ? "scale(1, 1) translate(-50%, -50%)" : "scale(0, 0) translate(-50%, -50%)"'
                                              transform-origin: left center
                                        - component: f7-block-header
                                          config:
                                            class:
                                              - no-margin
                                            style:
                                              position: absolute
                                              top: 50%
                                              left: 50%
                                              transition: transform 0.6s
                                              transform: '=items[props.state].state == "RUNNING" ? "scale(1, 1) translate(-50%, -50%)" : "scale(0, 0) translate(-50%, -50%)"'
                                              transform-origin: left center
    - component: f7-card-footer
      slots:
        default:
          - component: Label
            config:
              text: =props.footer

And after all of that, add the widget to the desired Page, and connect the Widget configuration to necessary items to finalize.

Cool that this works by only monitoring the ‘Things’ local network presence (via ping); no cloud dependencies! I’m happy with it ‘as is’, but always room for improvement. :smiley:

Best regards,
.

1 Like

I assume you are using an iPhone? Thanks for sharing your setup by the way!

1 Like

I’m on Android actually! The mobile animation issue is effecting the main UI in both the native mobile app and chrome.

Hi @DrRSatzteil

please excuse the late reply. At the moment there is a lot going on and there is little time left for the hobby. :wink:

I have checked the error pattern, but I cannot find a quick and easy solution. e.g. one line solution.

I can suggest removing the F7 preloader and building this structure myself. So you have everything in hand and can design yourself. Maybe there are professionals who will find a faster and better way. :smiley:

I hope this is a solution for all of you, even if it is not a quick one. Maybe this can also help @d0t .
It is working on my mobile phone and browser.

all the best,

Nico

My suggestion:

delete the f7-preloader and paste this snipped:

                                    - 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%

Complete Code:

uid: dishwasher_Nico
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: Mar 14, 2021, 12:35:30 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:
                                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
                                  - 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
1 Like

No worries Nico. For me my old version with the animation properties works fine even though this can only be considered luck given that these properties should not work…

I will look at your approach in the next couple of days, it is definitely better to have code that works without weird workarounds :wink: Thanks for your efforts!

1 Like

I finally updated my widget with your code @Nico_R. Seems to work fine for me, thank you! However the front door is still invisible on my iPads…

Maybe @d0t can try if this solves his issues.

1 Like

I’m back on an iPhone since my new employer hands out iOS devices. So I finally wanted to have this fixed for iOS devices as well. The solution is a hack I got from here: javascript - iOS 8 css rotate element disappears - Stack Overflow

I still have no clue why this is necessary but it does the trick for me and my iOS devices without breaking anything on other devices.

I updated the code in the first post!

So i had a xiaomi smart plug lying around and your excellent widget made me use it to monitor my dump dishwasher.I use this rule reading the power consumption and it works …ok

val Number MODE_OFF = 0
val Number MODE_ACTIVE = 1
val Number MODE_FINISHED = 2
rule "dishwasher"
when Item XiaomiMiSmartSocketPlug_ProvidedPower changed
then
  logInfo("Dishwasher Consumption State Machine","I am running this rule (Status "+DishwasherState.state+")")
  if (XiaomiMiSmartSocketPlug_ProvidedPower.state < 1.5 | W) {
       DishwasherState.postUpdate(MODE_OFF) 
       logInfo("Dishwasher Consumption State Machine","Dishwasher is OFF (Status "+DishwasherState.state+")")
    } 
    else if (XiaomiMiSmartSocketPlug_ProvidedPower.state > 30.0 | W) {
        DishwasherState.postUpdate(MODE_ACTIVE)
        logInfo("Dishwasher Consumption State Machine","Dishwasher is ON (Status "+DishwasherState.state+")")
    }
	else if (XiaomiMiSmartSocketPlug_ProvidedPower.state < 3.0 | W) {
        logInfo("Dishwasher Consumption State Machine","I am now checking if it's FINISHED (Status "+DishwasherState.state+")") 
		if (DishwasherState.state == MODE_ACTIVE) {
            DishwasherState.postUpdate(MODE_FINISHED)
            logInfo("Dishwasher Consumption State Machine","Dishwasher is FINISHED as it was ACTIVE before")
        } 
		else {
            logInfo("Dishwasher Consumption State Machine","I did not enter here (Status "+DishwasherState.state+")")
        }
    }
end	

my expression is

=items.DishwasherState.state == '0' ? "OFF" : items.DishwasherState.state == '1' ? "RUNNING" : items.DishwasherState.state == '2' ? "FINISHED" : "OFF"

and now i am out of ideas how to get the runtime…Any ideas?

I’m using the PersistenceExtensions: See my post here: Washing machine status widget - #3 by DrRSatzteil

You may also just reset an item to 0 when you enter MODE_ACTIVE and increase this number by one every minute while the current mode is still == MODE_ACTIVE.

Thanks for the great widget! Works as it should with my installation.
And then a question: is there some configuration to disable the “incoming” animation? The washer-widget doesn’t have that and some of my devices struggle with that animation. I’m not so firm in CSS and stuff, so I’m a bit at a loss here

Thanks!

Hi and thanks!

I think to remove the animations it should be enough to remove the lines with „transition: transform 0.6s“ nodes in the yaml code.

1 Like

Thanks! works!

How do you get the footer texts to change according to the dishwasher state? My footer is empty…

You can use an expression like this for the footer field:

'=items.dishwasher_status.state == "RUNNING" ? "Spült" :
    items.dishwasher_status.state == "FINISHED" ? "Beendet" : "Aus"'
1 Like