[OH3] Main UI - main_widget - part 1 - The main_widget

The “main_widget” project is a series of widgets to create a new mobile view for controlling your openHAB installation. For full functionality, you will need to install all widgets listed in the development thread.

Installation:

  • Add the non semantic tag “Floor” to all your floors and if you like, also add the widgetOrderIndex to them
  • Add the name of the floor group 8e.g. gGroundfloor) as a new non semantic tag to each room in that particular floor
  • Install all needed widgets for this projekt from the marketplace.
  • Create an new layout page in openHAB MainUI
  • Enter the code tab for the new page and paste the following code

config:
  label: openPage
  sidebar: true
  hideNavbar: true
  showFullscreenIcon: false
  hideSidebarIcon: true
  style:
    --f7-block-padding-horizontal: 0px
    --f7-navbar-height: 0
blocks:
  - component: oh-block
    config:
      stylesheet: |
        .block:first-child{
          margin-top: 15px;
          }
    slots:
      default:
        - component: oh-grid-row
          config: {}
          slots:
            default:
              - component: oh-grid-col
                config: {}
                slots:
                  default:
                    - component: widget:main_widget
                      config:
                        locationTitle:
                        scenesGroup:
                        securityGroup:
                        securityMode:
                        referencePIN:
masonry: null
grid: []

configure the main_widget on your new page with the missing information (some items/groups need to be definded.

Screenshots


Changelog

Version 0.3

  • fixed menu sorting and coloring
  • changed margins to better use screen space

Version 0.2

  • added menu entry sorting for floors and rooms [@Nic0205]
  • new config options for scene and security group and security mode [@hmerk]

Version 0.1

  • initial release

Resources


uid: main_widget
tags: []
props:
  parameters:
    - default: black
      description: Set default color for Text
      label: Text color
      name: textColor
      required: false
      type: TEXT
    - default: Somewhere
      description: Name for your weather location
      label: Weather Location
      name: locationTitle
      required: false
      type: TEXT
    - context: item
      description: Name of scenes group item
      label: Scenes Group
      name: scenesGroup
      required: false
      type: TEXT
    - context: item
      description: Name of security group item
      label: Security Group
      name: securityGroup
      required: false
      type: TEXT
    - context: item
      description: Security Mode Item
      label: Security Mode
      name: securityMode
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Sep 22, 2022, 3:58:17 PM
component: f7-block
config:
  style:
    display: flex
    flex-direction: column
    height: calc(100vh - var(--f7-toolbar-height) - var(--f7-safe-area-bottom) - var(--f7-safe-area-top))
    justify-content: space-between
    margin: 0
    padding: 0
    widht: 100vh
slots:
  default:
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
      slots:
        default:
          - component: f7-segmented
            config:
              style:
                flex: 1 1 auto
            slots:
              default:
                - component: oh-repeater
                  config:
                    for: baseMenu
                    fragment: true
                    in:
                      - name: Home
                      - name: Floors
                      - name: Rooms
                    map: loop.baseMenu.name
                    sourceType: array
                  slots:
                    default:
                      - component: oh-button
                        config:
                          action: variable
                          actionVariable: objVar
                          actionVariableValue:
                            selectSection: ="SECTION" + loop.baseMenu_idx
                          large: true
                          style:
                            color: '=vars.objVar.selectSection=="SECTION" + loop.baseMenu_idx ? textColor : "#8C8C8C"'
                            font-size: 28px
                            font-weight: 200
                            text-decoration: underline
                            text-decoration-color: '=vars.objVar.selectSection=="SECTION" + loop.baseMenu_idx ? "#F8BB00" : "transparent"'
                            text-underline-offset: 4px
                          text: =loop.baseMenu
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: space-between
                width: 100%
              visible: false
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) - 1
                    iconF7: chevron_left
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    for: menuArray
                    fragment: true
                    sourceType: itemsWithTags
                    itemTags: Floor
                    fetchMetadata: widgetOrder
                    map: loop.menuArray_source
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                for: menuButtonHome
                                fragment: true
                                in: =loop.menuArray
                                filter: loop.menuArray_idx == 0
                                map: ((loop.menuButtonHome.metadata && loop.menuButtonHome.metadata.widgetOrder && loop.menuButtonHome.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonHome_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: floor
                                      actionVariableValue: =loop.menuArray[loop.menuButtonHome_source.sort()[loop.menuButtonHome_idx].split('&')[1]].name
                                      style:
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexHome || 0) % loop.menuButtonHome_source.length) + loop.menuButtonHome_source.length + loop.menuButtonHome_idx) % loop.menuButtonHome_source.length
                                      text: =loop.menuArray[loop.menuButtonHome_source.sort()[loop.menuButtonHome_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexHome
                    actionVariableValue: =(vars.buttonIndexHome || 0) + 1
                    iconF7: chevron_right
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: center
                width: 100%
              visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION1") ? true : false : false'
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) - 1
                    iconF7: chevron_left
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    for: menuArray
                    fragment: true
                    sourceType: itemsWithTags
                    itemTags: Floor
                    fetchMetadata: widgetOrder
                    map: loop.menuArray_source
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                for: menuButtonFloor
                                fragment: true
                                in: =loop.menuArray
                                filter: loop.menuArray_idx == 0
                                map: ((loop.menuButtonFloor.metadata && loop.menuButtonFloor.metadata.widgetOrder && loop.menuButtonFloor.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonFloor_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: floor
                                      actionVariableValue: =loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split('&')[1]].name
                                      style:
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexFloor || 0) % loop.menuButtonFloor_source.length) + loop.menuButtonFloor_source.length + loop.menuButtonFloor_idx) % loop.menuButtonFloor_source.length
                                        color: '=vars.floor ==(loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split("&")[1]].name) ? textColor : "#8C8C8C"'
                                        text-decoration: underline
                                        text-decoration-color: '=vars.floor ==(loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split("&")[1]].name) ? "#F8BB00" : "transparent"'
                                        text-underline-offset: 4px
                                      text: =loop.menuArray[loop.menuButtonFloor_source.sort()[loop.menuButtonFloor_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexFloor
                    actionVariableValue: =(vars.buttonIndexFloor || 0) + 1
                    iconF7: chevron_right
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
          - component: f7-row
            config:
              style:
                align-items: center
                display: flex
                flex-direction: row
                flex-wrap: nowrap
                height: 2em
                justify-content: center
                width: 100%
              visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION2") ? true : false : false'
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) - 1
                    iconF7: chevron_left
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
                - component: oh-repeater
                  config:
                    for: menuArrayRoom
                    fragment: true
                    sourceType: itemsWithTags
                    itemTags: =vars.floor
                    fetchMetadata: widgetOrder
                    map: loop.menuArrayRoom_source
                  slots:
                    default:
                      - component: f7-row
                        config:
                          style:
                            display: flex
                            height: 2em
                            justify-content: center
                            overflow: hidden
                        slots:
                          default:
                            - component: oh-repeater
                              config:
                                for: menuButtonRoom
                                fragment: true
                                in: =loop.menuArrayRoom
                                filter: loop.menuArrayRoom_idx == 0
                                map: ((loop.menuButtonRoom.metadata && loop.menuButtonRoom.metadata.widgetOrder && loop.menuButtonRoom.metadata.widgetOrder.value) || 0).toString().padStart(3,'0') + '&' + loop.menuButtonRoom_idx
                              slots:
                                default:
                                  - component: oh-button
                                    config:
                                      action: variable
                                      actionVariable: room
                                      actionVariableValue: =loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split('&')[1]].name
                                      style:
                                        flex: 0 0 auto
                                        height: 2em
                                        order: =(((vars.buttonIndexRoom || 0) % loop.menuButtonRoom_source.length) + loop.menuButtonRoom_source.length + loop.menuButtonRoom_idx) % loop.menuButtonRoom_source.length
                                        color: '=vars.room ==(loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split("&")[1]].name) ? textColor : "#8C8C8C"'
                                        text-decoration: underline
                                        text-decoration-color: '=vars.room ==(loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split("&")[1]].name) ? "#F8BB00" : "transparent"'
                                        text-underline-offset: 4px
                                      text: =loop.menuArrayRoom[loop.menuButtonRoom_source.sort()[loop.menuButtonRoom_idx].split('&')[1]].label
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: buttonIndexRoom
                    actionVariableValue: =(vars.buttonIndexRoom || 0) + 1
                    iconF7: chevron_right
                    style:
                      color: "#F8BB00"
                      flex: 0 0 auto
                      height: 2em
    - component: f7-block
      config:
        style:
          flex: 1 1 auto
          overflow: scroll
          margin-top: -1em
          margin-bottom: -1em

      slots:
        default:
          - component: widget:main_widget_Weather_Card
            config:
              bigCard: true
              dateFormat: true
              itemPrefix: OneCallAPIweatherandforecast_
              locationTitle: =props.locationTitle
              sunIndicator: true
              visible: '=(!vars.objVar || ((vars.objVar.selectSection=="SECTION0") && !vars.objVar.selectThing)) ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              for: sceneItem
              groupItem: =props.scenesGroup
              sourceType: itemsInGroup
            slots:
              default:
                - component: widget:main_widget_Scene_Card
                  config:
                    scene: =loop.sceneItem.name
                    sceneName: =loop.sceneItem.label
                    visible: '=vars.objVar ? ((vars.objVar.selectSection + vars.objVar.selectThing)=="SECTION0Scenes") ? true : false : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: Blinds
              sourceType: itemsWithTags
            slots:
              default:
                - component: oh-repeater
                  config:
                    fetchMetadata: semantics,metadata,listWidget
                    filter: '(loop.shutterItem.type=="Rollershutter") ? true : false'
                    for: shutterItem
                    groupItem: =loop.equipmentItem.name
                    sourceType: itemsInGroup
                  slots:
                    default:
                      - component: widget:main_widget_Rollershutter_Card
                        config:
                          RollerItem: =loop.shutterItem.name
                          visible: '=vars.objVar.selectThing=="Rollers" ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: Lightbulb
              sourceType: itemsWithTags
            slots:
              default:
                - component: widget:main_widget_Light_Card
                  config:
                    equipmentItem: =loop.equipmentItem.name
                    visible: '=vars.objVar.selectThing=="Lights" ? true : false'
          - component: oh-repeater
            config:
              fetchMetadata: semantics,metadata,listWidget
              filter: loop.equipmentItem.metadata.semantics.config.hasLocation == vars.room
              for: equipmentItem
              itemTags: RadiatorControl
              sourceType: itemsWithTags
            slots:
              default:
                - component: oh-repeater
                  config:
                    fetchMetadata: semantics,metadata,listWidget
                    for: tempItem
                    groupItem: =loop.equipmentItem.name
                    sourceType: itemsInGroup
                  slots:
                    default:
                      - component: widget:Temp_Control
                        config:
                          style:
                            flex: 1 1 auto
                            overflow-y: auto
                            position: relative
                          visible: '=vars.objVar.selectThing=="Climate" ? true : false'
                          widgettrend: =loop.tempItem.name
          - component: widget:main_widget_Security_Card
            config:
              securityGroup: =props.securityGroup
              securityMode: =props.securityMode
              visible: '=vars.objVar ? ((vars.objVar.selectSection + vars.objVar.selectThing)=="SECTION0Security") ? true : false : false'
          - component: Label
            config:
              style:
                flex: 1 1 auto
                overflow-y: auto
                position: relative
              text: =vars.objVar.selectSection + vars.floor
              visible: "=vars.objVar ? true : false"
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
          margin-bottom: -2em
        visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION0") ? true : false : false'
      slots:
        default:
          - component: f7-segmented
            config:
              class:
                - segmented-strong
              style:
                --f7-segmented-strong-between-buttons: 0px
                --f7-segmented-strong-bg-color: transparent
                --f7-segmented-strong-button-font-weight: 300
                --f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
                --f7-segmented-strong-padding: 0px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Security
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Security" ? true : false'
                    icon-f7: shield_fill
                    iconColor: green
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Security" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Security" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Security" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Security
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Scenes
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Scenes" ? true : false'
                    icon-f7: rectangle_on_rectangle_angled
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Scenes" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Scenes" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Scenes" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Scenes
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Weather
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Weather" ? true : false'
                    icon-f7: cloud
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Weather" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Weather" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Weather" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Weather
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: HVAC
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="HVAC" ? true : false'
                    icon-f7: flame
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="HVAC" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="HVAC" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="HVAC" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: HVAC
    - component: f7-block
      config:
        style:
          flex: 0 0 auto
          overflow: scroll
          margin-bottom: -2em
        visible: '=vars.objVar ? (vars.objVar.selectSection=="SECTION0") ? false : true : false'
      slots:
        default:
          - component: f7-segmented
            config:
              class:
                - segmented-strong
              style:
                --f7-segmented-strong-between-buttons: 0px
                --f7-segmented-strong-bg-color: transparent
                --f7-segmented-strong-button-font-weight: 300
                --f7-segmented-strong-button-hover-bg-color: rgba(255, 255, 255, 0.15)
                --f7-segmented-strong-padding: 0px
            slots:
              default:
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Lights
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Lights" ? true : false'
                    icon-f7: lightbulb
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Lights" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Lights" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Lights" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Lights
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Climate
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Climate" ? true : false'
                    icon-f7: snow
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Climate" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Climate" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Climate" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Climate
                - component: oh-button
                  config:
                    action: variable
                    actionVariable: objVar
                    actionVariableValue:
                      selectSection: =vars.objVar.selectSection
                      selectThing: Rollers
                    class:
                      - padding-top-half
                      - display-flex
                      - flex-direction-column
                    fill: '=vars.objVar.selectThing=="Rollers" ? true : false'
                    icon-f7: archivebox
                    iconColor: textColor
                    iconSize: 20
                    style:
                      --f7-button-bg-color: '=vars.objVar.selectThing=="Rollers" ? "#F8BB00" : "transparent"'
                      --f7-button-border-radius: 15px
                      --f7-button-hover-bg-color: '=vars.objVar.selectThing=="Rollers" ? "F8BB00" : "transparent"'
                      --f7-button-padding-horizontal: 0px
                      --f7-button-padding-vertical: 0px
                      --f7-button-text-color: '=vars.objVar.selectThing=="Rollers" ? "#6A6A6A" : "#8C8C8C"'
                      font-size: 12px
                      height: auto
                    text: Rollers