Universal Conditioner Card

Hello community! I’m trying to build a universal conditioner widget for every conditioner model.
this is the first release, so there could be some bugs or options to be fine tuned, so feel free to tell me what are issues you will find.
This widget looks into “Model” scheme, find some defined tags (described below) and automatically show/hide widget options.
This widget is the first of the package of widgets that i would like to distribute. My idea is to develope a set of universal widgets suitable for everyone and usable for different brand devices.

First thing to be done is to configure a Group and set it as “HVAC” in Semantic Class.

Then, you have to set:

Switch (for power on/off) as “Type” and “Semantic class” → Switch
Mode item as “Type” (String), “Semantic Class” (Control) and “Semantic Property” (Temperature);
Setpoint item, “Type” (Number:Temperature), “Semantic Class” (Setpoint) and “Semantic Property” (Temperature);
Temperature item as “Type” (Number:Temperature), “Semantic Class” (Measurement) and “Semantic Property” (Temperature);
Fan speed item as “Type” (String) and “Semantic Class” (Fan);
Fan direction item as “Type” (String) and “Semantic Class” (Tilt)

Maybe nothing too much different from the setup you already have.

Screenshots


Changelog

  • Fixed displayState for Temperature and Setpoint items

Version 0.1

  • initial release

Resources

uid: Universal_Conditioner_Card_Humidity
tags: []
props:
  parameters:
    - description: Small title on top of the card
      label: Title
      name: climaTitle
      required: false
      type: TEXT
    - context: item
      description: Conditioner Group Equipment
      label: Conditioner Group Equipment
      name: groupItem
      required: true
      type: TEXT
timestamp: Oct 13, 2022, 3:37:49 PM
component: f7-card
config:
  noShadow: false
  padding: false
  style:
    background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 15px 1px rgba(0,0,0,0.3)
    height: auto
    margin-left: 5px
    margin-right: 5px
    padding: 0px
slots:
  content:
    - component: f7-card-content
      config:
        style:
          height: auto
      slots:
        default:
          - component: oh-icon
            config:
              icon: iconify:lucide:sun-snow
              style:
                color: rgb(33, 150, 243)
                position: absolute
                top: 23px
              width: 40px
          - component: f7-row
            config:
              style:
                margin-left: 50px
                margin-top: 0px
            slots:
              default:
                - component: Label
                  config:
                    style:
                      color: '=themeOptions.dark === "dark" ? "white" : "black"'
                      font-size: 15px
                      font-weight: 500
                    text: =props.climaTitle
          - component: oh-repeater
            config:
              filter: '((loop.switchItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.switchItem.type=="Switch")) ? true : false'
              fetchMetadata: semantics,metadata,listWidget
              sourceType: itemsWithTags
              itemTags: Switch
              for: switchItem
            slots:
              default:
                - component: oh-toggle
                  config:
                    color: blue
                    item: =loop.switchItem.name
                    style:
                      position: absolute
                      right: 3%
                      top: 20px
                      --f7-toggle-height: 20px
                      --f7-toggle-inactive-color: red
                      --f7-toggle-width: 40px
                      z-index: 98
          - component: f7-block
            config:
              style:
                display: flex
                justify-content: space-between
                margin-top: 0px
                margin-left: 35px
                width: 150px
            slots:
              default:
                - component: oh-repeater
                  config:
                    fetchMetadata: semantics,metadata,listWidget
                    filter: "(loop.tempItem.groupNames.indexOf(props.groupItem) >= 0) ? true : false"
                    for: tempItem
                    itemTags: Measurement,Temperature
                    sourceType: itemsWithTags
                  slots:
                    default:
                      - component: f7-chip
                        config:
                          style:
                            color: '=items[loop.tempItem.name].state >= "21" ? "red" : items[loop.tempItem.name].state >= "19" ? "black" : "blue"'
                            background: rgb(240,240,240)
                            font-weight: 500
                          text: "=items[loop.tempItem.name].displayState ? items[loop.tempItem.name].displayState : items[loop.tempItem.name].state"
                - component: oh-repeater
                  config:
                    filter: "(loop.setpointItem.groupNames.indexOf(props.groupItem) >= 0) ? true : false"
                    fetchMetadata: semantics,metadata,listWidget
                    sourceType: itemsWithTags
                    itemTags: Setpoint,Temperature
                    for: setpointItem
                  slots:
                    default:
                      - component: f7-chip
                        config:
                          style:
                            background: transparent
                            color: rgb(33, 150, 243)
                            font-weight: 500
                          text: '=items[loop.setpointItem.name].displayState ? items[loop.setpointItem.name].displayState : items[loop.setpointItem.name].state == "UNDEF" ? "Not set" : items[loop.setpointItem.name].state'
                - component: oh-repeater
                  config:
                    filter: "(loop.humidityItem.groupNames.indexOf(props.groupItem) >= 0) ? true : false"
                    fetchMetadata: semantics,metadata,listWidget
                    sourceType: itemsWithTags
                    itemTags: Measurement,Humidity
                    for: humidityItem
                  slots:
                    default:
                      - component: f7-chip
                        config:
                          style:
                            background: transparent
                            color: rgb(33, 150, 243)
                            font-weight: 500
                          text: '=items[loop.humidityItem.name].displayState ? items[loop.humidityItem.name].displayState : items[loop.humidityItem.name].state ? items[loop.humidityItem.name].state : ""'
          - component: f7-row
            config:
              style:
                margin-top: 3%
            slots:
              default:
                - component: f7-col
                  config:
                    style:
                      width: 73%
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,metadata,listWidget
                          filter: "(loop.tempItem.groupNames.indexOf(props.groupItem) >= 0) ? true : false"
                          for: tempItem
                          itemTags: Measurement,Temperature
                          sourceType: itemsWithTags
                        slots:
                          default:
                            - component: oh-trend
                              config:
                                style:
                                  --f7-theme-color-bg-color: transparent
                                  background: var(--f7-theme-color-bg-color)
                                  filter: opacity(100%)
                                  margin-left: 40px
                                  margin-top: 10%
                                  height: 100%
                                  z-index: 98
                                trendGradient: "=[themeOptions.dark === 'dark' ? 'rgb(33, 150, 243)' : ('red'),('white')]"
                                trendItem: =loop.tempItem.name
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,metadata,listWidget
                          filter: "(loop.humidityItem.groupNames.indexOf(props.groupItem) >= 0) ? true : false"
                          for: humidityItem
                          itemTags: Measurement,Humidity
                          sourceType: itemsWithTags
                        slots:
                          default:
                            - component: oh-trend
                              config:
                                style:
                                  --f7-theme-color-bg-color: transparent
                                  background: var(--f7-theme-color-bg-color)
                                  filter: opacity(100%)
                                  margin-left: 40px
                                  margin-top: 5px
                                  z-index: 98
                                trendGradient:
                                  - blue
                                  - black
                                trendItem: =loop.humidityItem.name
                - component: f7-col
                  config:
                    style:
                      width: 20px
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          filter: '((loop.switchItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.switchItem.type=="Switch")) ? true : false'
                          fetchMetadata: semantics,metadata,listWidget
                          sourceType: itemsWithTags
                          itemTags: Switch
                          for: switchItem
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                filter: '((loop.setpointItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.setpointItem.type=="Number:Temperature")) ? true : false'
                                fetchMetadata: semantics,metadata,listWidget
                                sourceType: itemsWithTags
                                itemTags: Setpoint,Temperature
                                for: setpointItem
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: command
                                      actionCommand: =Number(items[loop.setpointItem.name].state.split(' ')[0]) + 0.5
                                      actionItem: =loop.setpointItem.name
                                      iconColor: blue
                                      iconF7: arrow_up_circle
                                      iconSize: 25
                                      style:
                                        background: transparent
                                        height: 35px
                                        display: flex
                                        position: absolute
                                        right: 1%
                                        z-index: 98
                                      visible: '=items[loop.switchItem.name].state == "ON" ? true : false'
                                  - component: oh-button
                                    config:
                                      action: command
                                      actionCommand: =Number(items[loop.setpointItem.name].state.split(' ')[0]) - 0.5
                                      actionItem: =loop.setpointItem.name
                                      iconColor: blue
                                      iconF7: arrow_down_circle
                                      iconSize: 25
                                      style:
                                        background: transparent
                                        bottom: 5%
                                        height: 35px
                                        position: absolute
                                        right: 1%
                                        z-index: 98
                                      visible: '=items[loop.switchItem.name].state == "ON" ? true : false'
    - component: oh-repeater
      config:
        filter: '((loop.switchItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.switchItem.type=="Switch")) ? true : false'
        fetchMetadata: semantics,metadata,listWidget
        sourceType: itemsWithTags
        itemTags: Switch
        for: switchItem
      slots:
        default:
          - component: f7-card-footer
            config:
              visible: '=items[loop.switchItem.name].state == "ON" ? true : false'
              style:
                background: rgb(204, 204, 255)
                border-radius: 0 0 var(--f7-card-expandable-border-radius) var(--f7-card-expandable-border-radius)
                height: auto
            slots:
              default:
                - component: oh-repeater
                  config:
                    filter: '((loop.modeItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.modeItem.type=="String")) ? true : false'
                    fetchMetadata: semantics,metadata,listWidget
                    sourceType: itemsWithTags
                    itemTags: Control,Temperature
                    for: modeItem
                  slots:
                    default:
                      - component: oh-link
                        config:
                          action: options
                          actionItem: =loop.modeItem.name
                          style:
                            background: transparent
                            z-index: 98
                        slots:
                          default:
                            - component: f7-chip
                              config:
                                text: =loop.modeItem.label
                                style:
                                  width: auto
                                  color: white
                                  background: blue
                                  border-radius: 8px
                                  font-size: 15px
                                  font-weight: 500
                - component: f7-block
                  config:
                    style:
                      height: auto
                      padding: 0
                      display: flex
                  slots:
                    default:
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,metadata,listWidget
                          for: fanspeedItem
                          sourceType: itemsWithTags
                          itemTags: Fan
                          filter: '((loop.fanspeedItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.fanspeedItem.type=="String")) ? true : false'
                        slots:
                          default:
                            - component: oh-link
                              config:
                                action: options
                                actionItem: =loop.fanspeedItem.name
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      height: 20px
                                      icon: iconify:material-symbols:mode-fan
                                      style:
                                        color: rgb(191, 0, 255)
                                        margin-top: 3px
                      - component: oh-repeater
                        config:
                          fetchMetadata: semantics,metadata,listWidget
                          for: fandirectionItem
                          sourceType: itemsWithTags
                          itemTags: Tilt
                          filter: '((loop.fandirectionItem.groupNames.indexOf(props.groupItem) >= 0) && (loop.fandirectionItem.type=="String")) ? true : false'
                        slots:
                          default:
                            - component: oh-link
                              config:
                                action: options
                                actionItem: =loop.fandirectionItem.name
                              slots:
                                default:
                                  - component: oh-icon
                                    config:
                                      height: 20px
                                      icon: iconify:gis:direction
                                      style:
                                        color: rgb(191, 0, 255)
                                        margin-top: 3px
                                        margin-left: 10px

Waiting for your opinion!

Cheers!