openHAB 3 Tutorial 7 – Custom Widgets

Button Widget von “BangerTECH”

uid: Button
 props:
   parameters:
     - label: Headline
       name: headline
       required: false
       type: TEXT
     - label: Headline Color
       name: headlinecolor
       required: false
       type: TEXT
     - label: Headline Weight
       name: headlineweight
       required: false
       type: TEXT
     - label: Left Button
       name: leftButton
       required: false
       type: TEXT
     - label: Right Button
       name: rightButton
       required: false
       type: TEXT
     - context: item
       label: Item
       name: item
       required: false
       type: TEXT
     - label: Background
       name: background
       required: false
       type: TEXT
 timestamp: Feb 19, 2021, 9:32:06 PM
 component: f7-card
 config:
   style:
     background: '=(props.background) ? props.background : ""'
 slots:
   default:
     - component: Label
       config:
         text: '=(props.headline) ? props.headline : "Headline"'
         style:
           color: '=(props.headlinecolor) ? props.headlinecolor : "white"'
           padding-bottom: 0px
           padding-top: 15px
           margin-top: 0px
           margin-left: 25px
           font-weight: '=(props.headlineweight) ? props.headlineweight : "normal"'
     - component: f7-card-content
       slots:
         default:
           - component: f7-segmented
             config:
               raised: true
               round: true
               strong: true
             slots:
               default:
                 - component: oh-button
                   config:
                     text: '=(props.leftButton) ? props.leftbutton : "Anwesend"'
                     actionItem: =(props.item)
                     actionCommand: ON
                     action: command
                     active: =(items[props.item].state === 'ON')
                 - component: oh-button
                   config:
                     text: '=(props.rightButton) ? props.rightButton : "Abwesend"'
                     actionItem: =(props.item)
                     actionCommand: OFF
                     action: command
                     active: =(items[props.item].state === 'OFF')

Toggle Widget von “BangerTECH”

uid: command-button-heater
 tags:
 homekit-look
 in use props: parameters: description: A text prop
 label: Headline 1
 name: headline1
 required: false
 type: TEXT
 description: A text prop
 label: Headline 2
 name: headline2
 required: false
 type: TEXT
 context: item
 description: An item to control
 label: Item
 name: item
 required: false
 type: TEXT
 label: Headline Color
 name: headlinecolor
 required: false
 type: TEXT
 label: Headline Weight
 name: headlineweight
 required: false
 type: TEXT
 label: Headline Size
 name: headlinesize
 required: false
 type: TEXT
 label: Icon 1
 name: icon1
 required: false
 type: TEXT
 label: Icon 2
 name: icon2
 required: false
 type: TEXT
 label: Command 1
 name: command1
 required: true
 type: TEXT
 label: Command 2
 name: command2
 required: true
 type: TEXT
 label: Background
 name: background
 required: false
 type: TEXT
 label: Icon 1 Color
 name: iconcolor1
 required: false
 type: TEXT
 label: Icon 2 Color
 name: iconcolor2
 required: false
 type: TEXT
 parameterGroups: []
 timestamp: Feb 18, 2021, 1:10:08 PM
 component: f7-card
 config:
 style:
 noShadow: false
 class:
 padding
 border-radius: var(--f7-card-expandable-border-radius)
 box-shadow: '=(items[props.item].state === props.command2) ? (props.iconcolor2 ? "8px 8px 28px 1px " + props.iconcolor2 : "10px 10px 28px 1px rgba(255,234,5,0.3)") : "var(--f7-card-expandable-box-shadow)"'
 background-color: '=(items[props.item].state === props.command2) ? "rgb(255,255,255)" : "rgba(228,228,228,0.9)"'
 background: '=(props.background) ? props.background : "linear-gradient(to bottom, #003366 0%, #00ffff 100%)"'
 height: 8.5em
 width: 8.5em
 slots:
 content:
 component: f7-block config: style:   margin: 0px   padding: 0px   display: flex   flex-direction: column   align-items: center slots: default: component: Label
 config:
   text: '=(items[props.item].state === props.command1) ? ((props.headline1) ? props.headline1 : "Headline") : ((props.headline2) ? props.headline2 : "Headline")'
   style:
     color: '=(props.headlinecolor) ? props.headlinecolor : "white"'
     padding-bottom: 7px
     margin-top: -5px
     font-weight: '=(props.headlineweight) ? props.headlineweight : "normal"'
     font-size: '=(props.headlinesize) ? props.headlinesize: "13px"'
 component: f7-icon
 config:
   f7: '=(items[props.item].state === props.command2) ? (props.icon2 ? props.icon2 : "lightbulb_fill") : (props.icon1 ? props.icon1 : "lightbulb")'
   size: 65
   margin: 0px
   padding: 0px
   style:
     color: '=(items[props.item].state === props.command2) ? (props.iconcolor2 ? props.iconcolor2 : "rgba(255,234,5,1)") : (props.iconcolor1 ? props.iconcolor1 : "")'
 component: oh-link
 config:
 action: command
 actionItem: =props.item
 actionCommand: "=(items[props.item].state === props.command1) ? props.command2 : props.command1"
 style:
   position: absolute
   width: 100%
   height: 100%
   top: 0
   left: 0
   actionPosition: center
 actionFeedback: Done! 

Liquid Card Widget von rgrollfitz”

uid: darkLiquid_card
tags:
  - small
  - dark
  - custom
  - liquid
props:
  parameters:
    - context: item
      description: Set an item which you want to control
      label: Item
      name: item
      required: false
      type: TEXT
      groupName: general
    - description: The value symbol shown after the item-value
      label: Value symbol
      name: valueSymbol
      required: false
      type: TEXT
      groupName: general
    - description: valueSymbol high or low
      label: Value symbol position
      name: valueSymbolPos
      required: false
      type: BOOLEAN
      groupName: general
      advanced: true
    - description: Set the lowest value, that your item can have. (<b>default:</b> 0)
      label: Items MIN value
      name: minValue
      required: false
      type: TEXT
      groupName: general
    - description: Set the highest value, that your item can have. (<b>default:</b> 100)
      label: Items MAX value
      name: maxValue
      required: false
      type: TEXT
      groupName: general
    - description: Show trend graph instead of liquid background
      label: Trend graph
      name: showTrend
      required: false
      type: BOOLEAN
      groupName: general
    - label: Headline text
      name: headline
      required: false
      type: TEXT
      groupName: header
    - label: Subheadline text
      name: subheadline
      required: false
      type: TEXT
      groupName: header
    - label: Hero icon image url
      name: heroIcon
      required: false
      type: TEXT
      groupName: images
    - description: Activating Stepper element to control item which you selected above
      label: Show stepper buttons
      name: showStepper
      required: false
      type: BOOLEAN
      groupName: controls
    - description: Activating Toggle element to control item which you selected above
      label: Show toggle
      name: showToggle
      required: false
      type: BOOLEAN
      groupName: controls
    - description: Activating Slider element to control item which you selected above
      label: Show slider
      name: showSlider
      required: false
      type: BOOLEAN
      groupName: controls
  parameterGroups:
    - name: general
      label: General settings
      description: Most important widget settings
    - name: header
      label: Header area
    - name: controls
      label: Control settings
      description: Controls to manipulate your item-state (only use one of them)
    - name: images
      label: Images
timestamp: Feb 17, 2021, 8:17:46 PM
component: f7-block
config:
  style:
    position: relative
    -ms-user-select: None
    -moz-user-select: None
    -webkit-user-select: None
    user-select: None
  class:
    - no-padding
    - no-margin
slots:
  default:
    - component: oh-image
      config:
        url: "=props.heroIcon ? props.heroIcon : ''"
        style:
          position: absolute
          top: -15px
          right: -10px
          width: 100%
          max-width: min(max(50px, 15vw), 80px)
          z-index: 99
    - component: f7-card
      config:
        style:
          max-height: 200px
          background-color: rgb(57,60,76)
          border-radius: 20px
          overflow: hidden
          position: relative
      slots:
        default:
          - component: oh-repeater
            config:
              visible: "=props.showTrend ? false : true"
              sourceType: range
              for: liquid
              rangeStart: "=!props.minValue ? 0 : Number(props.minValue)"
              rangeStop: "=!props.maxValue ? 100 : Number(props.maxValue)"
            slots:
              default:
                - component: f7-block
                  config:
                    visible: =items[props.item].state == loop.liquid_idx
                    style:
                      background-image: url('data:image/svg+xml,%3C%3Fxml version="1.0" encoding="UTF-8" standalone="no"%3F%3E%3C!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"%3E%3Csvg width="100%25" height="100%25" viewBox="0 0 100%25 100%25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"%3E%3Cg transform="matrix(1,0,0,1.16583,0,-41.4573)"%3E%3Cpath d="M2100,51C1877.85,82.213 1653.26,55.095 1427.19,70.645C1309.15,78.764 1091.86,41.538 882.9,59.37C605.267,83.062 300.648,21.379 0,51L0,250L2100,250L2100,51Z" style="fill:url(%23_Linear1);"/%3E%3C/g%3E%3Cdefs%3E%3ClinearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-2,-214.44,250,-1.71552,1149,250)"%3E%3Cstop offset="0" style="stop-color:rgb(255,136,0);stop-opacity:1"/%3E%3Cstop offset="1" style="stop-color:rgb(255,197,28);stop-opacity:1"/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E%0A')
                      position: absolute
                      height: 100%
                      width: 100%
                      left: 0
                      bottom: "=Math.fround((Number(loop.liquid) - (!props.maxValue ? 100 : Number(props.maxValue))) * (100 / (!props.maxValue ? 100 : Number(props.maxValue) - (!props.minValue ? 0 : Number(props.minValue))))) + '%'"
                      z-index: 1
          - component: f7-card-content
            config:
              style:
                height: 100%
                display: flex
                flex-direction: column
                position: relative
                z-index: 999
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      z-index: 999
                  slots:
                    default:
                      - component: f7-col
                        slots:
                          default:
                            - component: Label
                              config:
                                propsParameterGroup: header
                                text: '=(props.headline) ? props.headline : "Headline"'
                                style:
                                  white-space: nowrap
                                  text-overflow: ellipsis
                                  overflow: hidden
                                  display: block
                                  width: 100%
                                  color: rgba(255,255,255,1)
                                  letter-spacing: .75px
                                  font-size: min(max(14px, 4vw), 21px)
                                  font-weight: 600
                            - component: Label
                              config:
                                actionPropsParameterGroup: header
                                text: '=(props.subheadline) ? props.subheadline : "Subheadline"'
                                style:
                                  white-space: nowrap
                                  text-overflow: ellipsis
                                  overflow: hidden
                                  color: rgba(255,255,255,.7)
                                  letter-spacing: .75px
                                  font-size: min(max(9px, 2.5vw), 12px)
                - component: f7-row
                  config:
                    style:
                      z-index: 999
                  slots:
                    default:
                      - component: f7-col
                        config:
                          class: '=props.valueSymbolPos ? props.valueSymbolPos : "align-items-flex-end"'
                          style:
                            display: flex
                            justify-content: flex-start
                            position: relative
                        slots:
                          default:
                            - component: Label
                              config:
                                text: =items[props.item].state
                                style:
                                  color: rgba(255,255,255,1)
                                  text-shadow: 2px 2px rgba(0,0,0,.25)
                                  font-size: min(max(32px, 9vw), 51px)
                                  font-weight: 600
                            - component: Label
                              config:
                                text: =props.valueSymbol
                                style:
                                  color: rgba(255,255,255,1)
                                  text-shadow: 2px 2px rgba(0,0,0,.25)
                                  font-size: min(max(21px, 5.75vw), 32px)
                                  font-weight: 600
                      - component: f7-col
                        config:
                          style:
                            display: flex
                            align-self: center
                            justify-content: flex-end
                            align-items: flex-end
                            flex-direction: column
                        slots:
                          default:
                            - component: oh-icon
                              config:
                                icon: power
                                visible: =items[props.item].state === "0"
                                action: command
                                actionOptions: COMMAND
                                actionItem: =props.item
                                actionPropsParameterGroup: action
                                actionCommand: ON
                                width: 20
                                height: 20
                                style:
                                  cursor: pointer
                                  filter: invert()
                            - component: oh-icon
                              config:
                                icon: power
                                visible: =items[props.item].state > "0"
                                action: command
                                actionOptions: COMMAND
                                actionItem: =props.item
                                actionCommand: OFF
                                width: 20
                                height: 20
                                style:
                                  cursor: pointer
                                  filter: invert(14%) sepia(99%) saturate(7416%) hue-rotate(0deg) brightness(94%) contrast(114%)
                - component: f7-row
                  slots:
                    default:
                      - component: f7-col
                        config:
                          class: '=props.alignActionLeft ? props.alignActionLeft : "justify-content-flex-end"'
                          style:
                            height: 28px
                            max-height: 28px
                            display: flex
                        slots:
                          default:
                            - component: oh-stepper
                              config:
                                class: '=props.showStepper ? props.showStepper : "display-none"'
                                raised: true
                                buttonsOnly: true
                                small: true
                                autorepeat: true
                                min: =props.minValue
                                max: =props.maxValue
                                step: 1
                                color: white
                                style:
                                  list-style-type: none
                                item: =props.item
                            - component: oh-toggle
                              config:
                                class: '=props.showToggle ? props.showToggle : "display-none"'
                                color: yellow
                                item: =props.item
                                style:
                                  align-self: flex-end
                            - component: oh-slider
                              config:
                                class: '=props.showSlider ? props.showSlider : "display-none"'
                                step: "1"
                                min: =props.minValue
                                max: =props.maxValue
                                item: =props.item
                                style:
                                  align-self: flex-end
                                  font-color: yellow
                            - component: oh-trend
                              config:
                                visible: "=props.showTrend ? true : false"
                                trendItem: =props.item
                                trendGradient:
                                  - "#FFE7DD"
                                  - "#FFD1BD"
                                style:
                                  position: absolute
                                  bottom: 0
                                  left: 0
                                  width: 100%
                                  height: 100%

Thermostat Widget von “Nico_R”

uid: thermostat
tags: []
props:
  parameters:
    - description: eg. living room
      label: location
      name: location
      required: false
      type: TEXT
    - description: Visual size of the control in px (default 400)
      label: size [px]
      name: size
      required: false
      type: TEXT
    - description: Minimum value
      label: minTemp
      name: minTemp
      required: true
      type: TEXT
    - description: Maximum value
      label: maxTemp
      name: maxTemp
      required: true
    - context: item
      description: Item to control
      label: Set point Item
      name: setPointItem
      required: true
      type: TEXT
    - context: item
      label: Item for current temperature
      name: currentPointItem
      required: true
      type: TEXT
    - context: item
      label: Item to toggle something
      name: toggleItem
      required: false
      type: TEXT
    - description: Control item unit eg °C
      label: unit
      name: unit
      required: false
      type: TEXT
    - label: Main-Color Thermostat
      name: colorThermostat
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color control ring
      name: colorControlRing
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color buttons
      name: colorButton
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color center
      name: colorCenter
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color Typo
      name: colorTypo
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color setPoint Marker
      name: colorSetMarker
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color currentPoint Marker
      name: colorCurrentMarker
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color bar linear gradient startPoint
      name: colorBarStartPoint
      required: false
      type: TEXT
      groupName: colors
      advanced: true
    - label: Color bar linear gradient endPoint
      name: colorBarEndPoint
      required: false
      type: TEXT
      groupName: colors
      advanced: true
  parameterGroups:
    - name: colors
      label: Color-Settings
timestamp: Jan 31, 2021, 11:39:14 AM
component: f7-card
slots:
  default:
    - component: f7-card-content
      slots:
        default:
          - component: f7-row
            config:
              resizableFixed: true
              resizable-absolute: true
              class:
                - justify-content-center
            slots:
              default:
                - component: f7-block
                  config:
                    class: thermostat
                    style:
                      flex-shrink: 0
                      --f7-block-margin-vertical: 0px
                      --f7-block-padding-vertical: 0px
                      --f7-block-padding-horizontal: 0px
                      padding-left: 0px
                      width: "=props.size ? Number(props.size)+'px' : '400px'"
                      height: "=props.size ? Number(props.size)+'px' : '400px'"
                      background: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
                      border-radius: 50%
                      border: 2px solid rgb(64, 60, 77)
                  slots:
                    default:
                      - component: f7-block
                        config:
                          class: bar
                          style:
                            margin-top: 0px
                            position: absolute
                            width: "=props.size ? (Number(props.size)*0.89) +'px' : '356px'"
                            height: "=props.size ? (Number(props.size)*0.89) +'px' : '356px'"
                            top: 50%
                            left: 50%
                            transform: translate(-50%, -50%)
                            border-radius: 50%
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: inner_bar
                                style:
                                  margin-top: 0
                                  position: absolute
                                  top: 50%
                                  left: 50%
                                  transform: translate(-50%, -50%)
                                  width: "=props.size ? (Number(props.size)*0.86) +'px' : '344px'"
                                  height: "=props.size ? (Number(props.size)*0.86) +'px' : '344px'"
                                  border-radius: 100%
                                  background-color: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
                                  z-index: 4 !important
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      style:
                                        content: ""
                                        display: block
                                        position: absolute
                                        width: 0
                                        height: 0
                                        border-top: "=props.size ? (Number(props.size)*0.175) +'px solid' : '70px solid'"
                                        border-left: "=props.size ? (Number(props.size)*0.175) +'px solid transparent' : '70px solid transparent'"
                                        border-right: "=props.size ? (Number(props.size)*0.175) +'px solid transparent' : '70px solid transparent'"
                                        border-bottom: "=props.size ? (Number(props.size)*0.375) +'px solid ' + (props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)') : '150px solid ' + (props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)')"
                                        bottom: "=props.size ? '-7px' : '-7px'"
                                        left: 50%
                                        transform: translate(-50%)
                            - component: f7-block
                              config:
                                class: hold left
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: 100%
                                  height: 100%
                                  clip: "=props.size ? 'rect(0px, ' + (Number(props.size)*0.89) +'px, ' + (Number(props.size)*0.89) +'px, ' + (Number(props.size)*0.89/2) + 'px)' : 'rect(0px, 356px, 356px, 178px)'"
                                  border-radius: 100%
                                  background-color: rgb(58, 55, 73)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: fill fill1
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        width: 100%
                                        height: 100%
                                        border-radius: 100%
                                        clip: "=props.size ? 'rect(0px, '+ (Number(props.size)*0.89/2) + 'px, ' + (Number(props.size)*0.89) + 'px, 0px)' : 'rect(0px, 178px, 356px, 0px)'"
                                        background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 20%,' + props.colorBarEndPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 20%,rgb(255, 73, 0) 100%)'"
                                        z-index: 1 !important
                                        animation: left 0.3s linear both
                                        animation-delay: 1s
                                        transition: transform 0.6s
                                        transform: "=(items[props.setPointItem].state.split(' ')[0] >= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > Number(props.maxTemp)) ? 'rotate(180deg)' : '')"
                            - component: f7-block
                              config:
                                class: hold right
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: 100%
                                  height: 100%
                                  clip: "=props.size ? 'rect(0px, ' + (Number(props.size)*0.89) + 'px, ' + (Number(props.size)*0.89) + 'px, ' + (Number(props.size)*0.89/2) + 'px)' : 'rect(0px, 356px, 356px, 178px)'"
                                  border-radius: 100%
                                  background-color: rgb(58, 55, 73)
                                  z-index: 3 !important
                                  transform: rotate(180deg)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: fill
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        width: 100%
                                        height: 100%
                                        border-radius: 100%
                                        z-index: 3 !important
                                        animation: right 1s linear both
                                        transition: transform 0.6s
                                  - component: f7-block
                                    config:
                                      class: fill fill2
                                      style:
                                        position: absolute
                                        margin-top: 0px
                                        width: 100%
                                        height: 100%
                                        border-radius: 50%
                                        z-index: 3 !important
                                        clip: "=props.size ? 'rect(0px, ' + (Number(props.size)*0.89/2) + 'px, ' + (Number(props.size)*0.89) + 'px, 0px)' : 'rect(0px, 178px, 356px, 0px)'"
                                        background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 40%,' + props.colorBarStartPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 40%,rgb(255, 158, 35) 100%)'"
                                        transform: "=(items[props.setPointItem].state.split(' ')[0] <= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))+20)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp))) ? 'rotate(180deg)' :  '')"
                            - component: f7-block
                              config:
                                class: span
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.89) +'px' : '356px'"
                                  font-weight: "=props.size ? (Number(props.size)*2) +'px' : '800'"
                                  position: absolute
                                  bottom: 0px
                                  text-align: center
                                  text-transform: uppercase
                                  font-size: "=props.size ? (Number(props.size)*0.0375) +'px' : '15px'"
                                  color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                  z-index: 99 !important
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: Heating
                      - component: f7-block
                        config:
                          class: shadow
                          style:
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.0625) +'px' : '25px'"
                            height: 86%
                            text-align: center
                            transition: 0.7s ease
                            animation: shadow 1.4s ease-out both
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: shadow-cube
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  top: 0
                                  width: "=props.size ? (Number(props.size)*0.0625) +'px' : '25px'"
                                  height: 0px
                                  box-shadow: "=props.size ? '0 0 ' + (Number(props.size)*0.1125) +'px ' + (Number(props.size)*0.0325) + 'px ' + (props.colorSetMarker ? props.colorSetMarker : 'rgba(255, 158, 35, 0.5)'): '0 0 45px 13px rgba(255, 158, 35, 0.5)'"
                      - component: f7-block
                        config:
                          class: markerContainer
                          style:
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.currentPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.currentPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.currentPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                            height: 82%
                            text-align: center
                            transition: 0.7s ease
                            opacity: 1
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: markerCurrent
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                                  height: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                                  background: "=props.colorCurrentMarker ? props.colorCurrentMarker : 'rgb(33, 150, 243)'"
                                  position: absolute
                                  transform: translate(-50%,-50%) rotate(135deg)
                                  left: 50%
                                  top: "=props.size ? (Number(props.size)*0.0375) +'px' : '15px'"
                                  border-radius: 50% 50% 50% 0
                                  box-shadow: 0 0 5px 1px rgb(48, 46, 56)
                                  z-index: 99 !important
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: number
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        top: 50%
                                        left: 50%
                                        transform: translate(-50%, -50%) rotate(-135deg)
                                        text-align: center
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =items[props.currentPointItem].state.split(' ')[0]
                                            style:
                                              font-size: "=props.size ? (Number(props.size)*0.04) +'px' : '14px'"
                                              color: white
                                              font-weight: bold
                      - component: f7-block
                        config:
                          class: markerContainer
                          style:
                            margin-top: 0px
                            position: absolute
                            top: 50%
                            left: 50%
                            transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
                            width: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                            height: 100%
                            text-align: center
                            transition: 0.7s ease
                            opacity: 1
                        slots:
                          default:
                            - component: f7-block
                              config:
                                class: markerSet
                                style:
                                  margin-top: 0px
                                  width: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                                  height: "=props.size ? (Number(props.size)*0.1) +'px' : '40px'"
                                  background: "=props.colorSetMarker ? props.colorSetMarker : 'rgb(230, 74, 25)'"
                                  position: absolute
                                  transform: translate(-50%,-50%) rotate(-45deg)
                                  left: 50%
                                  top: "=props.size ?  (Number(props.size)*Number(-0.0125)) +'px': '-5px'"
                                  border-radius: 50% 50% 50% 0
                                  box-shadow: 0 0 5px 1px rgb(48, 46, 56)
                                  z-index: 100 !important
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: number
                                      style:
                                        margin-top: 0px
                                        position: absolute
                                        top: 50%
                                        left: 50%
                                        transform: translate(-50%, -50%) rotate(45deg)
                                        text-align: center
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =items[props.setPointItem].state.split(' ')[0]
                                            style:
                                              font-size: "=props.size ? (Number(props.size)*0.04) +'px' : '14px'"
                                              color: white
                                              font-weight: bold
                      - component: f7-block
                        config:
                          class: center
                          style:
                            margin-top: 0px
                            position: absolute
                            width: "=props.size ? (Number(props.size)*0.65) +'px' : '260px'"
                            height: "=props.size ? (Number(props.size)*0.65) +'px' : '260px'"
                            background: "=props.colorControlRing ? props.colorControlRing : 'rgb(227, 228, 237)'"
                            animation: bound-in 0.6s ease forwards
                            top: 50%
                            left: 50%
                            transform: translate(-50%, -50%)
                            border-radius: 50%
                            box-shadow: 0px 15px 35px 11px rgba(46, 44, 58,0.60)
                        slots:
                          default:
                            - component: oh-toggle
                              config:
                                visible: "=props.toggleItem ? true : false"
                                item: =props.toggleItem
                                style:
                                  position: absolute
                                  bottom: 0%
                                  left: 50%
                                  transform: translate(-50%,-50%)
                                  color: "=props.colorButton ? props.colorButton + ' !important': ''"
                            - component: oh-button
                              config:
                                style:
                                  --f7-button-hover-bg-color: transparent
                                  --f7-button-pressed-bg-color: transparent
                                  width: 30%
                                  height: 50%
                                  position: absolute
                                  margin-top: 0px
                                  top: 50%
                                  left: 10%
                                  transform: translate(-50%, -50%)
                                  color: "=props.colorButton ? props.colorButton : ''"
                                action: command
                                actionItem: =props.setPointItem
                                actionCommand: =Number(items[props.setPointItem].state.split(' ')[0]) - 0.5
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      size: "=props.size ? (Number(props.size)*0.075) : '30'"
                                      style:
                                        position: absolute
                                        transform: translate(-50%, -50%)
                                        top: 50%
                                        margin-top: auto
                                      f7: arrow_turn_left_down
                            - component: oh-button
                              config:
                                style:
                                  --f7-button-hover-bg-color: transparent
                                  --f7-button-pressed-bg-color: transparent
                                  width: 30%
                                  height: 50%
                                  position: relative
                                  margin-top: 0px
                                  top: 50%
                                  left: 90%
                                  transform: translate(-50%, -50%)
                                  color: "=props.colorButton ? props.colorButton : ''"
                                action: command
                                actionItem: =props.setPointItem
                                actionCommand: =Number(items[props.setPointItem].state.split(' ')[0]) + 0.5
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      size: "=props.size ? (Number(props.size)*0.075) : '30'"
                                      style:
                                        position: absolute
                                        transform: translate(-50%, -50%)
                                        top: 50%
                                        margin-top: auto
                                      f7: arrow_turn_right_up
                            - component: f7-block
                              config:
                                class: small
                                style:
                                  margin-top: 0px
                                  position: absolute
                                  width: "=props.size ? (Number(props.size)*0.375) +'px' : '150px'"
                                  height: "=props.size ? (Number(props.size)*0.375) +'px' : '150px'"
                                  background: "=props.colorCenter ? props.colorCenter : 'rgb(248, 249, 250)'"
                                  text-align: center
                                  animation: bound-in-small 0.6s ease forwards
                                  top: 50%
                                  left: 50%
                                  transform: translate(-50%, -50%)
                                  border-radius: 50%
                                  box-shadow: 0px 5px 10px 5px rgba(96, 93, 111,0.19)
                              slots:
                                default:
                                  - component: f7-block
                                    config:
                                      class: heat
                                      style:
                                        font-size: "=props.size ? (Number(props.size)*0.0375) +'px' : '14px'"
                                        color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                        font-weight: 300
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: =props.location
                                  - component: f7-block
                                    config:
                                      class: heat
                                      style:
                                        font-size: "=props.size ? (Number(props.size)*0.1000) +'px' : '40px'"
                                        color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
                                        font-weight: 300
                                    slots:
                                      default:
                                        - component: Label
                                          config:
                                            text: "=props.unit ? items[props.setPointItem].state.split(' ')[0] + '' + props.unit : items[props.setPointItem].state.split(' ')[0]"
                                  - component: oh-image
                                    config:
                                      url: https://pbs.twimg.com/profile_banners/1102507312714002432/1609178314/1500x500
                                      style:
                                        position: absolute
                                        transform: translate(-50%)
                                        left: 50%
                                        width: 40%

Temp V2 Control Widget von “muelli1967”

uid: widget_f7-card_Temp_V2_Control
tags:
  - homekit-look
  - Soll Tag
  - in use
props:
  parameters:
    - description: Location?
      label: Prop 1
      name: prop1
      required: false
      type: TEXT
    - description: Thermostate icon f7
      label: f7 icon name
      name: icon1
      required: false
      type: TEXT
    - description: Humidity icon f7
      label: f7 icon name
      name: icon2
      required: false
      type: TEXT
    - context: item
      description: A Temperature item to display
      label: Item
      name: itemTemp
      required: false
      type: TEXT
    - context: item
      description: A Set-Temperature item to display
      label: Item
      name: itemTempSoll
      required: false
      type: TEXT
    - context: item
      description: An Humidity item to display
      label: Item
      name: itemHum
      required: false
      type: TEXT
    - context: item
      description: the valve state
      label: Item
      name: itemValve
      required: false
      type: TEXT
    - context: item
      description: Item for temperature channel
      label: Ambient temperature
      name: itemAmbientTemp
      required: false
      type: TEXT
    - context: item
      description: Item for outdoor temperature channel
      label: Outdoor temperature
      name: itemOutdoorTemp
      required: false
      type: TEXT
    - context: item
      description: Item for target temperature channel
      label: Target temperature
      name: itemTargetTemp
      required: true
      type: TEXT
    - context: item
      description: Item for operation mode channel
      label: Operation mode
      name: itemMode
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Feb 18, 2021, 1:40:25 PM
component: f7-card
config:
  style:
    noShadow: false
    class:
      - padding
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: var(--f7-card-expandable-box-shadow)
    background-color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "white" : (Number.parseFloat(items[props.itemTemp].state.split(" ")[0]) > 23) ? "white" : "rgba(228,228,228,0.9)"'
    height: 8.5em
    min-width: 9.5em
    max-width: 400px
slots:
  content:
    - component: f7-block
      config:
        style:
          margin-left: -6px
          padding: -1px
          display: flex
          flex-direction: column
          align-items: start
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: f7-icon
            config:
              f7: =props.icon1
              size: 22
              class:
                - align-self-center
              style:
                margin-left: -6px
                margin-top: 0px
                color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "black" : (Number.parseFloat(items[props.itemTemp].state.split(" ")[0]) > 23) ? "black" : "rgb(0,0,0,0.5)"'
          - component: Label
            config:
              text: =props.prop1
              style:
                font-size: 14px
                font-weight: 500
                margin-left: -4px
                margin-top: 0px
                color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "black" : (Number.parseFloat(items[props.itemTemp].state.split(" ")[0]) > 23) ? "black" : "rgb(0,0,0,0.5)"'
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: Label
            config:
              text: =(Number.parseFloat(items[props.itemTemp].state.split(" ")[0]) * 100 / 100).toFixed(1) + '°'
              style:
                font-size: 32px
                line-height: 1.1
                font-weight: 498
                margin-left: 0px
                margin-top: 0px
                color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "black" : (Number.parseFloat(items[props.itemTemp].state.split(" ")[0]) > 23) ? "black" : "rgb(0,0,0,0.5)"'
    - component: f7-row
      config:
        class:
          - justify-content-left
      slots:
        default:
          - component: f7-icon
            config:
              f7: =props.icon2
              size: 16
              style:
                top: 5px
                left: 0px
                color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "red" : "rgb(0,0,0,0.5)"'
          - component: Label
            config:
              text: =(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) * 100 / 100).toFixed(0) + '%'
              visible: =props.itemHum !== undefined
              style:
                top: 5px
                left: 0px
                font-size: 13px
                font-weight: 500
                color: '=(Number.parseFloat(items[props.itemHum].state.split(" ")[0]) > 60) ? "red" : "rgb(0,0,0,0.5)"'
    - component: f7-row
      config:
        class:
          - float-right
      slots:
        default:
          - component: f7-icon
            config:
              f7: arrowshape_turn_up_right
              size: 16
              style:
                opacity: 0.5
                bottom: 0px
                right: -45px
                color: rgb(0,0,0,0.5)
          - component: f7-chip
            config:
              bgColor: '=(Number.parseFloat(items[props.itemValve].state.split(" ")[0]) > 15) ? "orange" : "green"'
              text: =(Number.parseFloat(items[props.itemTempSoll].state.split(" ")[0]) * 100 / 100).toFixed(0)
              style:
                color: white
                size: 20
                z-index: 2
                bottom: 75px
                border-radius: 25px 25px 25px 25px
                margin-top: 2px
                right: -5px
    - component: oh-trend
      config:
        trendItem: =[props.itemTemp]
        style:
          --f7-theme-color-bg-color: transparent
          background: var(--f7-theme-color-bg-color)
          filter: opacity(30%)
          position: absolute
          width: 100%
          height: 100%
          top: 0
          left: 2
          z-index: 1
    - component: oh-link
      config:
        action: popup
        actionModal: widget:HM_Thermostat_Control_Final
        actionModalConfig:
          itemAmbientTemp: =props.itemAmbientTemp
          itemOutdoorTemp: =props.itemOutdoorTemp
          itemTargetTemp: =props.itemTargetTemp
          itemMode: =props.itemMode
        style:
          position: absolute
          width: 100%
          height: 100%
          top: 0
          left: 0

6 Gedanken zu “openHAB 3 Tutorial 7 – Custom Widgets

  1. Hi, vielen Dank für die Anregungen. Könntest du im zweiten Beispiel die fehlerhaften Zeilenumbrüche und fehlenden “-” korrigieren?

      1. Hallo,
        Ich habe bei OH3 mittlerweile das Problem, dass mir dir Widgets folgenden Fehler senden:
        “Attempting to send a state update of an item which doesn’t exist: undefined”

        Das passiert sogar, wenn ich das Widget erstelle. Also den Code kopiere und als neues Widget erstelle. Dann wird der Fehler das erste mal gesetzt. Er taucht jedes mal auf, wenn ich die Main-Page öffne.
        Kannst du da weiterhelfen?

          1. Die richtigen Items sind gesetzt. Was mich etwas verwundert, ist dass der Fehler auftritt sobald ich das Widget erstelle. Also wenn ich im Reiter “Developer Tools” ein neues Widget mit dem Code erstelle.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert