# Pool Monitor Card

**URL:** <https://community.openhab.org/t/pool-monitor-card/164693>\
**Category:** UI Widgets\
**Tags:** beta\
**Created:** [June 27, 2025, 4:12pm UTC](https://community.openhab.org/t/pool-monitor-card/164693 "2025-06-27T16:12:38Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![MikeTheTux](https://community.openhab.org/letter_avatar_proxy/v4/letter/m/c68b51/32.png) [@MikeTheTux](https://community.openhab.org/u/MikeTheTux)\
**Post date:** [June 27, 2025, 4:12pm UTC](https://community.openhab.org/t/pool-monitor-card/164693/1 "2025-06-27T16:12:38Z")

</div>

![](https://community-openhab-org.s3.dualstack.eu-central-1.amazonaws.com/original/3X/4/9/4991a77cb46a45dc4b294b3952a9a1a4337f7163.png)

Inspired by [Home-Assistant Pool Monitor Card v2](https://github.com/wilsto/pool-monitor-card) I created this openHAB Widget.

## Screenshots

t.b.d.

## Changelog

- v0.1
  - initial beta version - using hard coded items

- v0.2
  - show target values (time and ORP), only when active

- v0.3
  - added items to show delta
  - added inputs to change targets (time, ORP)
  - added button to confirm recommendation
  - show time of last measure

## Resources

```yaml
uid: pool_monitor_card
tags: []
props:
  parameters: []
  parameterGroups: []
timestamp: Jul 14, 2025, 8:17:56 AM
component: f7-card
config:
  style:
    border-radius: 12px
    padding: 2%
    width: 196%
slots:
  default:
    - component: f7-block
      config:
        style:
          padding: 0
      slots:
        default:
          - component: oh-button
            config:
              action: analyze
              actionAnalyzerItems:
                - ICOpool_Temperature
                - ICOpool_PH
                - ICOpool_OxydoReductionPotential
                - ICOpool_Salt
                - ShellyPoolControl_FlowPower_Power
                - ShellyPoolControl_ChlorinatorPower_Power
                - ShellyPool_PowerConsumption
              style:
                --f7-button-text-transform: none
                color: white
                font-size: 1em
                font-weight: bold
                margin-top: 12px
                text-align: left
              text: "='🌡️ Temperature: ' + items.ICOpool_Temperature.state +
                ((items.ICOpool_TemperatureDelta.numericState >=
                Math.max(items.ICOpool_Temperature.numericState * 0.02, 0.1)) ?
                ' ↗️ ' : ((items.ICOpool_TemperatureDelta.numericState <=
                -Math.max(items.ICOpool_Temperature.numericState * 0.02, 0.1)) ?
                ' ↘️ ' : ' ➡️ ')) + items.ICOpool_TemperatureDelta.displayState"
          - component: f7-block
            config:
              style:
                background: linear-gradient(to right, blue 0%, green 25%, orange 50%, red 100%)
                border-radius: 8px
                height: 20px
                margin-bottom: -19px
                position: relative
                z-index: 5
          - component: oh-slider
            config:
              color: "=(Number.parseFloat(items.ICOpool_Temperature.state.split(' ')[0]) < 25)
                ? 'orange' :
                ((Number.parseFloat(items.ICOpool_Temperature.state.split('
                ')[0]) > 28) ? 'orange' : 'green')"
              disabled: true
              item: ICOpool_Temperature
              label: true
              max: 40
              min: 5
              style:
                margin-bottom: 12px
                position: relative
                z-index: 50
          - component: oh-button
            config:
              action: analyze
              actionAnalyzerItems:
                - ICOpool_Temperature
                - ICOpool_PH
                - ICOpool_OxydoReductionPotential
                - ICOpool_Salt
                - ShellyPoolControl_FlowPower_Power
                - ShellyPoolControl_ChlorinatorPower_Power
                - ShellyPool_PowerConsumption
              style:
                --f7-button-text-transform: none
                color: white
                font-size: 1em
                font-weight: bold
                text-align: left
              text: "='🧪 PH level: ' + items.ICOpool_PH.state +
                ((items.ICOpool_PHDelta.numericState >=
                Math.max(items.ICOpool_PH.numericState * 0.02, 0.1)) ? ' ↗️ ' :
                ((items.ICOpool_PHDelta.numericState <=
                -Math.max(items.ICOpool_PH.numericState * 0.02, 0.1)) ? ' ↘️ ' :
                ' ➡️ ')) + items.ICOpool_PHDelta.displayState"
          - component: f7-block
            config:
              style:
                background: linear-gradient(to right, red 20%, green 50%, red 80%)
                border-radius: 8px
                height: 20px
                margin-bottom: -19px
                z-index: 5
          - component: oh-slider
            config:
              color: "=(Number.parseFloat(items.ICOpool_PH.state.split(' ')[0]) < 7.2) ?
                'orange' : ((Number.parseFloat(items.ICOpool_PH.state.split('
                ')[0]) > 7.6) ? 'orange' : 'green')"
              disabled: true
              item: ICOpool_PH
              max: 8.6
              min: 6.2
              step: 0.1
              style:
                margin-bottom: 12px
                z-index: 50
          - component: oh-button
            config:
              action: analyze
              actionAnalyzerItems:
                - ICOpool_Temperature
                - ICOpool_PH
                - ICOpool_OxydoReductionPotential
                - ICOpool_Salt
                - ShellyPoolControl_FlowPower_Power
                - ShellyPoolControl_ChlorinatorPower_Power
                - ShellyPool_PowerConsumption
              style:
                --f7-button-text-transform: none
                color: white
                font-size: 1em
                font-weight: bold
                text-align: left
              text: "='🧼 ORP: ' + items.ICOpool_OxydoReductionPotential.state +
                ((items.ICOpool_OxydoReductionPotentialDelta.numericState >=
                Math.max(items.ICOpool_OxydoReductionPotential.numericState *
                0.02, 0.1)) ? ' ↗️ ' :
                ((items.ICOpool_OxydoReductionPotentialDelta.numericState <=
                -Math.max(items.ICOpool_OxydoReductionPotential.numericState *
                0.02, 0.1)) ? ' ↘️ ' : ' ➡️ ')) +
                items.ICOpool_OxydoReductionPotentialDelta.displayState"
          - component: f7-block
            config:
              style:
                background: linear-gradient(to right, red 0%, green 30%, green 50%, green 70%,
                  red 100%)
                border-radius: 8px
                height: 20px
                margin-bottom: -19px
                z-index: 5
          - component: oh-slider
            config:
              color: "=(Number.parseFloat(items.ICOpool_OxydoReductionPotential.state.split('
                ')[0]) < 650) ? 'orange' :
                ((Number.parseFloat(items.ICOpool_OxydoReductionPotential.state\
                .split(' ')[0]) > 750) ? 'orange' : 'green')"
              disabled: true
              item: ICOpool_OxydoReductionPotential
              max: 800
              min: 500
              step: 0.1
              style:
                margin-bottom: 12px
                z-index: 50
          - component: oh-button
            config:
              action: analyze
              actionAnalyzerItems:
                - ICOpool_Temperature
                - ICOpool_PH
                - ICOpool_OxydoReductionPotential
                - ICOpool_Salt
                - ShellyPoolControl_FlowPower_Power
                - ShellyPoolControl_ChlorinatorPower_Power
                - ShellyPool_PowerConsumption
              style:
                --f7-button-text-transform: none
                color: white
                font-size: 1em
                font-weight: bold
                text-align: left
              text: "='🧂 Salinity: ' + items.ICOpool_Salt.state +
                ((items.ICOpool_SaltDelta.numericState >=
                Math.max(items.ICOpool_Salt.numericState * 0.02, 0.1)) ? ' ↗️ '
                : ((items.ICOpool_SaltDelta.numericState <=
                -Math.max(items.ICOpool_Salt.numericState * 0.02, 0.1)) ? ' ↘️ '
                : ' ➡️ ')) + items.ICOpool_SaltDelta.displayState"
          - component: f7-block
            config:
              style:
                background: linear-gradient(to right, red 0%, green 50%, red 100%)
                border-radius: 8px
                height: 20px
                margin-bottom: -19px
                z-index: 5
          - component: oh-slider
            config:
              color: "=(Number.parseFloat(items.ICOpool_Salt.state.split(' ')[0]) < 2500) ?
                'orange' : ((Number.parseFloat(items.ICOpool_Salt.state.split('
                ')[0]) > 3500) ? 'orange' : 'green')"
              disabled: true
              item: ICOpool_Salt
              max: 4000
              min: 2000
              step: 0.1
              style:
                margin-bottom: 12px
                z-index: 50
          - component: f7-row
            slots:
              default:
                - component: f7-col
                  config:
                    align: right
                    width: auto
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: rule
                          actionRule: PoolControl_StartStopFlow
                          iconColor: "=(items.ShellyPoolControl_FlowPower_Power.state == 'ON') ? 'blue' :
                            'gray'"
                          iconF7: "=(items.ShellyPoolControl_FlowPower_Power.state == 'ON') ?
                            'play_rectangle_fill' : 'play_rectangle'"
                          text: 💦
                - component: f7-col
                  config:
                    align: right
                    width: auto
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: rule
                          actionRule: PoolControl_StartStopChlorinator
                          iconColor: "=(items.ShellyPoolControl_ChlorinatorPower_Power.state == 'ON') ?
                            'orange' : 'gray'"
                          iconF7: "=(items.ShellyPoolControl_ChlorinatorPower_Power.state == 'ON') ?
                            'play_rectangle_fill' : 'play_rectangle'"
                          text: 🧼
                - component: f7-col
                  config:
                    align: right
                    width: auto
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: rule
                          actionRule: PoolControl_SwitchPhase
                          disabled: "=(items.ShellyPoolControl_ChlorinatorPower_Power.state == 'ON') ?
                            true : false"
                          iconColor: green
                          iconF7: "=(items.ShellyPoolControl_ChlorinatorPhase_Power.state == 'ON') ?
                            'plus_slash_minus' : 'minus_slash_plus'"
                          text: 🔋
          - component: f7-row
            slots:
              default:
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: oh-input
                        config:
                          item: PoolControl_CurrentEnd
                          sendButton: true
                          style:
                            color: white
                            font-size: 0.95em
                            font-weight: bold
                          type: time
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          style:
                            color: white
                            font-size: 1em
                            font-weight: bold
                          text: "=(items.ShellyPoolControl_ChlorinatorPower_Power.state == 'ON') ? '🎯 ' +
                            items.PoolControl_ORPTarget.state: ''"
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          style:
                            color: gray
                            font-size: 0.8em
                          text: ='🔌 ' + items.ShellyPool_PowerConsumption.state
          - component: f7-row
            slots:
              default:
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: oh-input
                        config:
                          item: PoolControl_RegularStart
                          sendButton: true
                          style:
                            color: gray
                            font-size: 0.8em
                            font-weight: bold
                          type: time
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: oh-input
                        config:
                          item: PoolControl_ORPTarget
                          sendButton: true
                          style:
                            color: gray
                            font-size: 0.8em
                          type: text
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          style:
                            color: gray
                            font-size: 0.8em
          - component: f7-row
            slots:
              default:
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: oh-input
                        config:
                          item: PoolControl_RegularEnd
                          sendButton: true
                          style:
                            color: gray
                            font-size: 0.8em
                            font-weight: bold
                          type: time
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: command
                          actionCommand: ok
                          actionItem: ICOpool_RecommendationStatus
                          style:
                            --f7-button-text-transform: none
                            color: gray
                            font-size: 0.8em
                          text: ='⚖️ ' + items.ICOpool_RecommendationTitle.state
                - component: f7-col
                  config:
                    align: center
                    width: auto
                  slots:
                    default:
                      - component: Label
                        config:
                          style:
                            color: gray
                            font-size: 0.8em
                          text: = 'last measure 🔃 ' + items.ICOpool_LastUpdate.displayState

```

---

<div class="post-metadata">

**Author:** ![Baschtlwaschtl](https://community.openhab.org/user_avatar/community.openhab.org/baschtlwaschtl/32/70481_2.png) [@Baschtlwaschtl](https://community.openhab.org/u/Baschtlwaschtl)\
**Post date:** [June 27, 2025, 6:06pm UTC](https://community.openhab.org/t/pool-monitor-card/164693/2 "2025-06-27T18:06:24Z")

</div>

Hello, looks good  
May I ask what kind of measuring device you use?  
I want to do that too.

Greets

---

<div class="post-metadata">

**Author:** ![MikeTheTux](https://community.openhab.org/letter_avatar_proxy/v4/letter/m/c68b51/32.png) [@MikeTheTux](https://community.openhab.org/u/MikeTheTux)\
**Post date:** [June 27, 2025, 7:04pm UTC](https://community.openhab.org/t/pool-monitor-card/164693/3 "2025-06-27T19:04:17Z")

</div>

ICO pool v2 Salt, bridged from Home-Assistant, as openHAB binding is not available.

---

<div class="post-metadata">

**Author:** ![Baschtlwaschtl](https://community.openhab.org/user_avatar/community.openhab.org/baschtlwaschtl/32/70481_2.png) [@Baschtlwaschtl](https://community.openhab.org/u/Baschtlwaschtl)\
**Post date:** [June 27, 2025, 7:27pm UTC](https://community.openhab.org/t/pool-monitor-card/164693/4 "2025-06-27T19:27:56Z")

</div>

> [@MikeTheTux](#):
>
> ICO pool v2 Salt

Oh okay.. Thx

---

<div class="post-metadata">

**Author:** ![MikeTheTux](https://community.openhab.org/letter_avatar_proxy/v4/letter/m/c68b51/32.png) [@MikeTheTux](https://community.openhab.org/u/MikeTheTux)\
**Post date:** [July 17, 2025, 2:23pm UTC](https://community.openhab.org/t/pool-monitor-card/164693/5 "2025-07-17T14:23:49Z")

</div>

> [@MikeTheTux](#):
>
> bridged from Home-Assistant, as openHAB binding is not available

In the meanwhile an openHAB binding is available: [Ondilo - Bindings | openHAB](https://next.openhab.org/addons/bindings/ondilo/)
