Reimplement my Sitemap (>1000 Items) to WebUI using the yamlcomposer and yaml based widget templates

After my last project “porting my HABPanel dashboard to the standard WebUI”, I decided to move on to the Basic UI this time.

The previously mentioned dashboard presented key data reasonably well, but it was far from sufficient on its own. To handle this, I had a very extensive sitemap that provided access to all 1,174 of my items. In the dashboard, I would either access this sitemap directly via the start URL to reach everything or jump straight to specific sections—like the heating or ventilation menus—using sub-URLs.

Having had a positive experience porting the dashboard, I decided to try the same approach with the sitemap.

The following advantages were decisive for me:

  1. A WebUI-based solution can still be accessed via the Android app.
  2. I can now customize minor details of the app UI design to my liking.
  3. I no longer need to embed the sitemap as an iframe within a dashboard popup.
  4. The layout is now consistent between the dashboard and the new app design.
  5. It offers entirely new interaction possibilities.

Initially, I tried implementing this using “standard” widgets. Unfortunately, I didn’t get very far because the widget API is quite limited. Since I was working with the YAML composer at the time, I opted for a hybrid approach; consequently, my solution makes extensive use of the YAML composer.

I also initially attempted to implement each of my screens as a separate “Page.” However, I noticed a perceptible 0.5-second lag during navigation, so I switched to using a single central page for the app and another for the tablet dashboard. Within these pages, I simply switch between widgets.

For me, the implementation is 100% feature-complete—meaning:

  • The layout behaves exactly like the app’s; it is responsive and switches between one-column and two-column layouts. The following features have also been implemented:
  • Dimmer with Hue color support
  • Text input
  • Roller shutter controls
  • Selection (using both item options and custom mappings)
  • Setpoints
  • Choice buttons
  • Toggle buttons
  • Text boxes with the ability to navigate to sub-pages (as widgets)

Additionally, value colors and the visibility flag have been implemented.

For now, everything is implemented to the point where it can fully replace the old version and serve as the detail navigation in my tablet dashboard.

Anything beyond this can be added next.

P.S. The layout still needs some fine-tuning. :slight_smile:

Here are a few brief notes:

There is exactly one page each for the Basic UI replacement and the tablet dashboard. The related templates can be found here

Everything else is implemented via widgets

These widget templates consist essentially of template snippets that are included using yamlcompose. The actual UI components are, in turn, implemented within these template snippets

WebUI on my phone

Integration in my dashboard

Here is an example of what YAML Composer can do, applied to alexaechocontrol.yaml

version: 1

things:
  &BRIDGE amazonechocontrol:account:account1:
    isBridge: true
    label: Amazon Account
    config:
      discoverSmartHome: 0
      pollingIntervalSmartHomeAlexa: 30
      pollingIntervalSmartSkills: 120

templates:
  alexa:
    things:
      amazonechocontrol:${type|default('echo')}:account1:pFF_${package_id}_Alexa:
        bridge: *BRIDGE
        label: Alexa Device @ pFF_${package_id}_Alexa
        config:
          serialNumber: ${ENV["CUSTOM_ALEXA_" + (package_id | upper) + "_SERIAL"]}

packages:
  Bathroom: !insert alexa
  Bedroom: !insert alexa?type=echoshow
  Fitnessroom: !insert alexa
  Makeuproom: !insert alexa
  Corridor: !insert alexa
  Livingroom: !insert alexa
  Workroom: !insert alexa
  Indoor: !insert alexa

and to make getting started easier for newcomers

the two main entry-point pages are

The App page loads the “start” widget App. The other one is a more complex example, but not to this post.

All actions used anywhere open just widgets in a popup

These “navigation” popups are getting assigned additional css transitions via app_navigation.js, simulating a slide-in/slide-out effect similar to using standard pages.

The corresponding JS and CSS files can be found here

I am not a YAML guy; I looked at this like a dear in headlights… (almost dismissive like: another thing I don’t know what do do with it)

… until a light bulb went on… (though a day later) :slight_smile:

And I am now in my second day playing with this; my 70 LED downlights are now .inc templated with thing, items, link and group and members creation. Same for my 5 batteries :slight_smile:

Simply awesome!! (y)

Thank you.

… as I continue to rework anything with multiple yet same things.

variables:
  topic_base: ArgyleCourt/Shed/Tower/PACE_MODBUS/${bms}
  item_prefix: BMS_${bms}
  group_prefix: grp_BMS_${bms}

things:
  mqtt:topic:mosquitto:${package_id}:
    bridge: mqtt:broker:mosquitto
    label: Teway Cell Battery ${bms}
    location: Shed Tower

    channels:
      pack_current:
        type: number
        label: BMS ${bms} Current
        config:
          stateTopic: ${topic_base}/pack/current

      pack_voltage:
        type: number
        label: BMS ${bms} Pack voltage
        config:
          stateTopic: ${topic_base}/pack/voltage

      pack_soc:
        type: number
        label: BMS ${bms} State of charge
        config:
          stateTopic: ${topic_base}/pack/soc

      pack_soh:
        type: number
        label: BMS ${bms} State of health
        config:
          stateTopic: ${topic_base}/pack/soh

      pack_capacity_remaining:
        type: number
        label: BMS ${bms} Remaining capacity
        config:
          stateTopic: ${topic_base}/pack/capacity_remain

      pack_capacity_full:
        type: number
        label: BMS ${bms} Full capacity
        config:
          stateTopic: ${topic_base}/pack/capacity_full

      pack_capacity_design:
        type: number
        label: BMS ${bms} Design capacity
        config:
          stateTopic: ${topic_base}/pack/capacity_design

      cell_voltage_1:
        type: number
        label: BMS ${bms} Cell 1 voltage
        config:
          stateTopic: ${topic_base}/cells/1
          min: 2
          max: 4

      cell_voltage_2:
        type: number
        label: BMS ${bms} Cell 2 voltage
        config:
          stateTopic: ${topic_base}/cells/2
          min: 2
          max: 4

      cell_voltage_3:
        type: number
        label: BMS ${bms} Cell 3 voltage
        config:
          stateTopic: ${topic_base}/cells/3
          min: 2
          max: 4

      cell_voltage_4:
        type: number
        label: BMS ${bms} Cell 4 voltage
        config:
          stateTopic: ${topic_base}/cells/4
          min: 2
          max: 4

      cell_voltage_5:
        type: number
        label: BMS ${bms} Cell 5 voltage
        config:
          stateTopic: ${topic_base}/cells/5
          min: 2
          max: 4

      cell_voltage_6:
        type: number
        label: BMS ${bms} Cell 6 voltage
        config:
          stateTopic: ${topic_base}/cells/6
          min: 2
          max: 4

      cell_voltage_7:
        type: number
        label: BMS ${bms} Cell 7 voltage
        config:
          stateTopic: ${topic_base}/cells/7
          min: 2
          max: 4

      cell_voltage_8:
        type: number
        label: BMS ${bms} Cell 8 voltage
        config:
          stateTopic: ${topic_base}/cells/8
          min: 2
          max: 4

      cell_voltage_9:
        type: number
        label: BMS ${bms} Cell 9 voltage
        config:
          stateTopic: ${topic_base}/cells/9
          min: 2
          max: 4

      cell_voltage_10:
        type: number
        label: BMS ${bms} Cell 10 voltage
        config:
          stateTopic: ${topic_base}/cells/10
          min: 2
          max: 4

      cell_voltage_11:
        type: number
        label: BMS ${bms} Cell 11 voltage
        config:
          stateTopic: ${topic_base}/cells/11
          min: 2
          max: 4

      cell_voltage_12:
        type: number
        label: BMS ${bms} Cell 12 voltage
        config:
          stateTopic: ${topic_base}/cells/12
          min: 2
          max: 4

      cell_voltage_13:
        type: number
        label: BMS ${bms} Cell 13 voltage
        config:
          stateTopic: ${topic_base}/cells/13
          min: 2
          max: 4

      cell_voltage_14:
        type: number
        label: BMS ${bms} Cell 14 voltage
        config:
          stateTopic: ${topic_base}/cells/14
          min: 2
          max: 4

      cell_voltage_15:
        type: number
        label: BMS ${bms} Cell 15 voltage
        config:
          stateTopic: ${topic_base}/cells/15
          min: 2
          max: 4

      cell_voltage_16:
        type: number
        label: BMS ${bms} Cell 16 voltage
        config:
          stateTopic: ${topic_base}/cells/16
          min: 2
          max: 4

      sum_cell_voltages:
        type: number
        label: BMS ${bms} Sum of cell voltages
        config:
          stateTopic: ${topic_base}/cell_sum
          min: 40
          max: 60

      sum_cell_voltage_half_1:
        type: number
        label: BMS ${bms} Cell voltage half 1
        config:
          stateTopic: ${topic_base}/cell_half_1
          min: 20
          max: 30

      sum_cell_voltage_half_2:
        type: number
        label: BMS ${bms} Cell voltage half 2
        config:
          stateTopic: ${topic_base}/cell_half_2
          min: 20
          max: 30

      battery_temp_1:
        type: number
        label: BMS ${bms} Battery temperature 1
        config:
          stateTopic: ${topic_base}/temp/battery_1
          min: 0
          max: 50

      battery_temp_2:
        type: number
        label: BMS ${bms} Battery temperature 2
        config:
          stateTopic: ${topic_base}/temp/battery_2
          min: 0
          max: 50

      battery_temp_3:
        type: number
        label: BMS ${bms} Battery temperature 3
        config:
          stateTopic: ${topic_base}/temp/battery_3
          min: 0
          max: 50

      battery_temp_4:
        type: number
        label: BMS ${bms} Battery temperature 4
        config:
          stateTopic: ${topic_base}/temp/battery_4
          min: 0
          max: 50

      mosfet_temperature:
        type: number
        label: BMS ${bms} MOSFET temperature
        config:
          stateTopic: ${topic_base}/temp/mosfet
          min: 0
          max: 100

      environment_temperature:
        type: number
        label: BMS ${bms} Environment temperature
        config:
          stateTopic: ${topic_base}/temp/environment
          min: 0
          max: 50

items:
  # Groups belonging to this BMS
  ${group_prefix}:
    type: Group
    label: BMS ${bms}

  ${group_prefix}_Cells:
    type: Group
    label: BMS ${bms} Cells
    groups: ["${group_prefix}", grp_Persist_Influx_Tewaycell]

  ${group_prefix}_Cells_1_to_8:
    type: Group
    label: BMS ${bms} Cells 1 to 8
    groups: ["${group_prefix}", gPersist_rrd4j]

  ${group_prefix}_Cells_9_to_16:
    type: Group
    label: BMS ${bms} Cells 9 to 16
    groups: ["${group_prefix}"]

  ${group_prefix}_Pack_Data:
    type: Group
    label: BMS ${bms} Pack data
    groups: [grp_Persist_Influx_Tewaycell]

  ${group_prefix}_Temperatures:
    type: Group
    groups: ["${group_prefix}", grp_Persist_Influx_Tewaycell]

  # MQTT-linked pack data
  ${item_prefix}_Current:
    type: Number
    label: BMS ${bms} Current
    icon: gPersist_rrd4j
    groups: ["${group_prefix}", gPersist_rrd4j, "${group_prefix}_Pack_Data"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_current

  ${item_prefix}_Voltage:
    type: Number
    label: BMS ${bms} Voltage
    icon: gPersist_rrd4j
    groups: ["${group_prefix}", gPersist_rrd4j, "${group_prefix}_Pack_Data"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_voltage

  ${item_prefix}_State_of_charge:
    type: Number
    label: BMS ${bms} State of charge
    icon: battery3
    groups: ["${group_prefix}", gPersist_rrd4j, "${group_prefix}_Pack_Data"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_soc

  ${item_prefix}_State_of_health:
    type: Number
    label: BMS ${bms} State of health
    icon: battery3
    groups: ["${group_prefix}", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:pack_soh

  ${item_prefix}_Remaining_capacity:
    type: Number
    label: BMS ${bms} Remaining capacity
    icon: battery3
    groups: ["${group_prefix}", "${group_prefix}_Pack_Data"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_capacity_remaining

  ${item_prefix}_Full_capacity:
    type: Number
    label: BMS ${bms} Full capacity
    icon: battery5
    groups: ["${group_prefix}"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_capacity_full

  ${item_prefix}_Design_capacity:
    type: Number
    label: BMS ${bms} Design capacity
    icon: battery4
    groups: ["${group_prefix}"]
    channel: mqtt:topic:mosquitto:${package_id}:pack_capacity_design

  # MQTT-linked cell voltages
  ${item_prefix}_Cell_1_voltage:
    type: Number
    label: BMS ${bms} Cell 1 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_1

  ${item_prefix}_Cell_2_voltage:
    type: Number
    label: BMS ${bms} Cell 2 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_2

  ${item_prefix}_Cell_3_voltage:
    type: Number
    label: BMS ${bms} Cell 3 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_3

  ${item_prefix}_Cell_4_voltage:
    type: Number
    label: BMS ${bms} Cell 4 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_4

  ${item_prefix}_Cell_5_voltage:
    type: Number
    label: BMS ${bms} Cell 5 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_5

  ${item_prefix}_Cell_6_voltage:
    type: Number
    label: BMS ${bms} Cell 6 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_6

  ${item_prefix}_Cell_7_voltage:
    type: Number
    label: BMS ${bms} Cell 7 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_7

  ${item_prefix}_Cell_8_voltage:
    type: Number
    label: BMS ${bms} Cell 8 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_1_to_8", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_8

  ${item_prefix}_Cell_9_voltage:
    type: Number
    label: BMS ${bms} Cell 9 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_9

  ${item_prefix}_Cell_10_voltage:
    type: Number
    label: BMS ${bms} Cell 10 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_10

  ${item_prefix}_Cell_11_voltage:
    type: Number
    label: BMS ${bms} Cell 11 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_11

  ${item_prefix}_Cell_12_voltage:
    type: Number
    label: BMS ${bms} Cell 12 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_12

  ${item_prefix}_Cell_13_voltage:
    type: Number
    label: BMS ${bms} Cell 13 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_13

  ${item_prefix}_Cell_14_voltage:
    type: Number
    label: BMS ${bms} Cell 14 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_14

  ${item_prefix}_Cell_15_voltage:
    type: Number
    label: BMS ${bms} Cell 15 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_15

  ${item_prefix}_Cell_16_voltage:
    type: Number
    label: BMS ${bms} Cell 16 voltage
    icon: battery
    groups: ["${group_prefix}", "${group_prefix}_Cells", "${group_prefix}_Cells_9_to_16", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:cell_voltage_16

  # MQTT-linked calculated BMS values and temperatures
  ${item_prefix}_Cell_voltage_total:
    type: Number
    label: BMS ${bms} Cell voltage total
    icon: battery
    groups: ["${group_prefix}", gPersist_rrd4j]
    channel: mqtt:topic:mosquitto:${package_id}:sum_cell_voltages

  ${item_prefix}_Voltage_Sum_Cells_1_to_8:
    type: Number
    label: BMS ${bms} Voltage Sum Cells 1 to 8
    icon: battery3
    groups: ["${group_prefix}"]
    channel: mqtt:topic:mosquitto:${package_id}:sum_cell_voltage_half_1

  ${item_prefix}_Voltage_Sum_Cells_9_to_16:
    type: Number
    label: BMS ${bms} Voltage Sum Cells 9 to 16
    icon: battery3
    groups: ["${group_prefix}"]
    channel: mqtt:topic:mosquitto:${package_id}:sum_cell_voltage_half_2

  ${item_prefix}_Battery_temperature_1:
    type: Number
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:battery_temp_1

  ${item_prefix}_Battery_temperature_2:
    type: Number
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:battery_temp_2

  ${item_prefix}_Battery_temperature_3:
    type: Number
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:battery_temp_3

  ${item_prefix}_Battery_temperature_4:
    type: Number
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:battery_temp_4

  ${item_prefix}_MOSFET_temperature:
    type: Number
    label: BMS ${bms} MOSFET temperature
    icon: temperature
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:mosfet_temperature

  ${item_prefix}_Environment_temperature:
    type: Number
    groups: ["${group_prefix}", "${group_prefix}_Temperatures"]
    channel: mqtt:topic:mosquitto:${package_id}:environment_temperature

  # Unlinked supporting items retained from BMS 1
  ${item_prefix}_Battery_Max_Voltage:
    type: Number
    label: BMS ${bms} Battery Max Voltage
    icon: battery5
    groups: ["${group_prefix}", gPersist_rrd4j]

  ${item_prefix}_Battery_Min_Voltage:
    type: Number
    label: BMS ${bms} Battery Min Voltage
    icon: battery1
    groups: ["${group_prefix}", gPersist_rrd4j]

  ${item_prefix}_Cell_Max_Voltage:
    type: Number
    label: BMS ${bms} Cell Max Voltage
    icon: battery5
    groups: ["${group_prefix}"]

  ${item_prefix}_Cell_Min_Voltage:
    type: Number
    label: BMS ${bms} Cell Min Voltage
    icon: battery1
    groups: ["${group_prefix}"]

  ${item_prefix}_Cells_1_to_8_Period:
    type: Number
    label: BMS ${bms} Cells 1 to 8 Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Cells_9_to_16_Period:
    type: Number
    label: BMS ${bms} Cells 9 to 16 Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Current_Period:
    type: Number
    label: BMS ${bms} Current Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Delta_Between_Battery_Halves:
    type: Number
    label: BMS ${bms} Delta Between Battery Halves
    icon: gPersist_rrd4j
    groups: ["${group_prefix}", gPersist_rrd4j]

  ${item_prefix}_SOC_Period:
    type: Number
    label: BMS ${bms} SOC Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Temperature_Period:
    type: Number
    label: BMS ${bms} Temperature Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Voltage_Delta_Period:
    type: Number
    label: BMS ${bms} Voltage Delta Period
    icon: calendar
    groups: ["${group_prefix}"]

  ${item_prefix}_Voltage_Period:
    type: Number
    label: BMS ${bms} Voltage Period
    icon: calendar
    groups: ["${group_prefix}"]

version: 1

packages:
  tewaycell_4: !include
    file: $pkg/teway-cell.inc.yaml
    vars:
      bms: 4

The sitemap is something I’d like to tackle too; thanks for sharing.

You could just type:

packages:
  tewaycell_4: !include $pkg/teway-cell.inc.yaml?bms=4

Even better, in your package file:

variables:
  bms: ${package_id | split("_") | last}
  ... the rest is the same

Then in the main file:

packages:
  tewaycell_1: !include $pkg/teway-cell.inc.yaml
  tewaycell_2: !include $pkg/teway-cell.inc.yaml
  tewaycell_3: !include $pkg/teway-cell.inc.yaml
  tewaycell_4: !include $pkg/teway-cell.inc.yaml

And the package automatically extracts the bms number out of the package name

Perhaps open a new topic if you’d like to bounce off ideas about yaml composer. I’m so happy to see people find value in it!

Can I deduct from your reply that you wrote the YAMLcomposer?!

If so then kudo to you!

Thanks for the examples; but, before I do shorthand I need to “get” the basic syntax :slight_smile:

The issue for my use of ‘dismissive’ (and I shall be forgiven) stems from being one of those people, who look at OH when a major update comes along and then need a year to decide to actually upgrade it. :slight_smile:

Coming from v1 and my system “just works”, and looking at it once a year, there are (without a doubt) developments and concepts I have neither grasped their impact, nor even understood (yet).

Yes! :slight_smile:

I updated the post above with more suggestions :slight_smile:

I finished the design almost too.


this is the design running on my phone


and this, the version running on my tablet

the page source code from the example above can be found here