Why can't I get a counter (number of) lights that are on?

Hello,

I’m trying to get the room card widget to show the number of lights that are “ON” with this widget Card_room_12 posted here.

The original script appears to count the number of items based on a dimmer value over 0

text: "=(Number(items[props.status].state) > 0) ? items[props.status].state : ''"

However, my lights operate in a state of either ON or OFF and I set the scirpt to this.

text: "=(Number(items[props.status].state) === 'ON') ? items[props.status].state : '

Of course, this isn’t working.
Here’s the the group.


and my modified version of the widget

uid: Card_room_12
tags: []
props:
  parameters:
    - label: Header
      name: text_header
      required: false
      type: TEXT
    - description: icon name without ".png", located in static/icons/ folder
      label: Icon
      name: iconimage
      required: false
      type: TEXT
    - description: HEX or rgba
      label: Backgroundcolor
      name: bgcolor
      required: false
      type: TEXT
    - description: Page which will be opened as popup
      label: Page ID
      name: page
      required: false
    - context: item
      description: select group for status lights
      label: Item
      name: status
      required: false
      type: TEXT
    - context: item
      description: select item for heating
      label: Item
      name: heating
      required: false
      type: TEXT
    - context: item
      description: select item for temperature
      label: Item
      name: temp
      required: false
      type: TEXT
    - context: item
      description: select item for set temperature
      label: Item
      name: settemp
      required: false
      type: TEXT
    - context: item
      description: select item for humidity
      label: Item
      name: humidity
      required: false
      type: TEXT
    - context: item
      description: select item for motion
      label: Item
      name: motion
      required: false
      type: TEXT
    - context: item
      description: select item for illuminance
      label: Item
      name: illuminance
      required: false
      type: TEXT
    - context: item
      description: select item for door state(s)
      label: Item
      name: door_state
      required: false
      type: TEXT
    - context: item
      description: select item for door lock(s)
      label: Item
      name: door_lock
      required: false
      type: TEXT
    - context: item
      description: select item for blinds group (SUM)
      label: Item
      name: blinds_closed
      required: false
      type: TEXT
    - context: item
      description: select item for speaker(s)
      label: Item
      name: speakers
      required: false
      type: TEXT
    - context: item
      description: select item for windows(s)
      label: Item
      name: windows
      required: false
      type: TEXT
    - context: item
      description: select item for numbers of windows
      label: Item
      name: windows_numbers
      required: false
      type: TEXT
    - context: item
      description: select item for boiler temp
      label: Item
      name: boiler_temp
      required: false
      type: TEXT
timestamp: Nov 22, 2021, 9:51:22 AM
component: f7-card
config:
  style:
    noShadow: false
    class:
      - padding: 0px
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    height: 125px
    margin-left: 5px
    margin-right: 5px
slots:
  content:
    - component: f7-block
      config:
        style:
          position: absolute
          top: -5px
          left: 50px
      slots:
        default:
          - component: Label
            config:
              text: "=props.text_header ? props.text_header : 'Set Props'"
              style:
                font-size: 17px
                font-weight: 600
                margin-left: 0px
                margin-top: 0px
    - component: f7-block
      config:
        style:
          position: absolute
          bottom: -37px
          left: 16px
      slots:
        default:
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.status ? true : false"
              text: "=(Number(items[props.status].state) === 'ON') ? items[props.status].state : ''"
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: "=(items[props.status].state === 'ON') ? 'lightbulb' : 'lightbulb_slash'"
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: =items[props.heating].state === 'ON'
              text: "=items[props.heating].state === 'ON' ? '' : ''"
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: flame
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.door_state ? true : false"
              text: "=items[props.door_state].state === 'ON' ? '' : ''"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: "=items[props.door_state].state === 'ON' ? 'door-open' : 'door-closed'"
                    style:
                      filter: "='brightness(' + (themeOptions.dark === 'dark' ? '1' : '0.4') + ')'"
                      height: 18px
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=items[props.windows].state === 'OPEN' ? true : false"
              text: "=items[props.windows_numbers].state > 0 ? items[props.windows_numbers].state : ''"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: window-open
                    style:
                      filter: "='brightness(' + (themeOptions.dark === 'dark' ? '1' : '0.4') + ')'"
                      height: 18px
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.door_lock ? true : false"
              text: "=items[props.door_lock].state === 'ON' ? '' : ''"
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: "=items[props.door_lock].state === 'ON' ? 'lock_open' : 'lock'"
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=(Number(Math.floor(items[props.blinds_closed].state)) > 0) ? true : false"
              text: "=(Number(items[props.blinds_closed].state) === 0) ? '' : Math.floor(items[props.blinds_closed].state)"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: "=(Number(items[props.blinds_closed].state) === 0) ? 'cinemascreen-30' : 'cinemascreen-100'"
                    style:
                      filter: "='brightness(' + (themeOptions.dark === 'dark' ? '100' : '0.3') + ')'"
                      height: 18px
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=items[props.speakers].state === 'PLAY' ? true : false"
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: "=items[props.speakers].state === 'PLAY' ? 'speaker_2' : 'speaker'"
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.illuminance ? true : false"
              text: =items[props.illuminance].displayState
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: sun_min
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.motion ? true : false"
              text: =items[props.motion].state
            slots:
              media:
                - component: oh-icon
                  config:
                    color: "=(items[props.motion].state === 'Motion') ? 'blue' : 'gray'"
                    icon: "=(items[props.motion].state === 'Motion') ? 'motion' : 'motion'"
                    style:
                      filter: "='brightness(' + (themeOptions.dark === 'dark' ? '1' : '0.4') + ')'"
                      height: 18px
    - component: f7-block
      config:
        style:
          position: absolute
          bottom: -65px
          left: 16px
      slots:
        default:
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.temp ? true : false"
              text: "=(items[props.temp].displayState  ? items[props.temp].displayState : items[props.temp].state) +  (props.settemp ? ' (' + items[props.settemp].state + ')' : '')"
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: thermometer
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.humidity ? true : false"
              text: =items[props.humidity].displayState
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconF7: drop
              iconSize: 18
          - component: f7-chip
            config:
              style:
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              visible: "=props.boiler_temp ? true : false"
              text: =items[props.boiler_temp].state
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: waterheater2
                    style:
                      filter: "='invert(' + (themeOptions.dark === 'dark' ? '1' : '0') + ')'"
                      height: 18px
    - component: oh-image
      config:
        url: ='/static/icons/' + props.iconimage + '.png'
        style:
          position: absolute
          left: 16px
          top: 10px
          height: 25px
          opacity: 0.7
        visible: "=props.iconimage ? true : false"
    - component: oh-link
      config:
        action: popup
        actionModal: ='page:' + props.page
        style:
          position: absolute
          left: 0px
          top: 0px
          height: 110px
          width: 100%

In that widget the props.status variable refers to a group item that is configured with a count aggregation function. That means that the actual counting of the lights that are ON or OFF is not done in the widget, but that the state of that group item is a number that represents how many lights are on at that time. The line

text: "=(Number(items[props.status].state) > 0) ? items[props.status].state : ''"

is not counting how may lights have a state > 0. It is converting the string form of the group item’s state to a number variable so that it can be compared to 0 numerically. Your version is trying to force the unknown state of an item into a numerical type and then compare that numerical type to 'ON' with strict equality. This will always be false because a numerical type will never equal a string type with strict equality.

If you want to get the same functionality, do not change the original code, just make sure to configure a group item properly and set the status property to the name of that item.

2 Likes

To elaborate a little, the Group item needs to be assigned as sub-type Number and not Switch, because you want its state to be a numeric count. The GUI slightly misleading labels the Group sub-type as ‘member type’, while they need not be related at all.

It used to be the case that one could define a Group:Switch:OR(ON,OFF) (for example) and if you put that on the sitemap using [%s]in the label, you'd get ON or OFF for the state based on the states of the members. However, if you used a[%d]` you’d get the count of the Items that are ON.

I think it also worked in Rules using getStateAs(DecimalType) to get the count from a Group:Switch or Group:Contact.

I have no idea if this hidden little feature is still around in OH 3. I just ran a quick experiment and it appears not to work in MainUI any more.

probably I misunderstand rossky and rich (and when they talk then us hobbyist have to listen devotionally :slight_smile: ) but you simply add that SUM feature to the group:

I edited the Item (group) GroupPlayRoomLights and am now getting the correct count of lights that are ON

  • Members Base Type = Number
  • Aggregation Function = SUM

Thank you. Now that this is working, I have another question as to how I might count items that are ON and another count for items that are OFF.

In this post, I’ve shared how to get a report on the status of Things that are part of a Group Item (GroupStatus)

It would be nice to create a widget that had the count of both ON and OFF items.

Thank you for your time and attention. I’m truly grateful for this community and always look for a way to give back.

There was a reason we suggested COUNT. Count what? You choose, count “ON”, count “OFF” (note NULLs and UNDEFs excluded there). Of course for two answers you will need two groups.

In DSL rules you count the total number of group members by

GroupPlayRoomLights.members.size

and the total number of items in that group which are OFF by

GroupPlayRoomLights.members.filter[ i | i.state == "OFF" ].size

OP wants his counts in the UI, so they have to get into some Item state or another.

He runs a rule to create a report over offline and online items. As always there are several ways in OH to achieve your goal.
Creating a group with

Group:String:COUNT("OFFLINE")     OfflineDevices

in a text file and import this file into your GUI based items (if I get you right) is also another way to achieve his goal.

Can this be coded in the GUI? or do I need to post into an .items file?

Can what be coded? A Group is just an Item, you know how to get and display an Item’s state.

Can the OFFLINE count be setup in the GUI? or is this level of detail limited to .item ?

Yes, if you have a recent enough OH version - beyond 3.1 release I think.
MainUI had some omissions before.

But -

COUNT produces a number.
Group:Number:COUNT("OFFLINE")
the Group type is about the Group state, not the member types.
You can have a Switch type Group with all Dimmer members, for example.

Hey rossko, could you point me in the right direction? I have checked all release notes of Milestone releases but could not find any information regarding this.
Where, how can you make use of Group:COUNT in MainUI?

Create a new Item of Group type. Then edit its properties.

and then?
No idea what you are talking about.

there is no COUNT
image

just SUM which was exactly the suggestion in my post above.

still seems to be a bug: