TV Remote Control on BasicUI thanks to Buttongrid!

Thanks for the new Buttongrid widget on BasicUI sitemap!

Note, I created the sitemap using JRuby, but this can be easily created using an xtext sitemap file as well, and I’d imagine also through the Main UI although I have never looked into that.

The benefit of using jruby to generate the sitemap is that I can DRY repetitive things, e.g. I have multiple TVs in the house. I only need to write the TV section just once, and I can create the frames for all the TVs for me.

This is the code I used (WIP):

APP_COLUMNS = 4
APPLICATIONS = [
  ["youtube.leanback.v4", "Youtube", "if:fa:youtube"],
  ["netflix", "Netflix", "if:mdi:netflix"],
  ["amazon", "Amazon", "if:arcticons:primevideo"],
  ["com.pplus.webapp.prod-intl", "Paramount+", "if:arcticons:paramount-plus"],
  ["cdp-30", "Plex", "if:mdi:plex"],
  ["com.disney.disneyplus-prod", "Disney+", "if:tabler:brand-disney"]
].then do |apps|
  max_row = (apps.size / APP_COLUMNS) + 1
  columns_in_the_last_row = apps.size % APP_COLUMNS
  # Center the last row by padding it with empty cells
  last_row_padding = ((APP_COLUMNS - columns_in_the_last_row) / 2) + 1

  apps.map.with_index do |app, i|
    row = (i / APP_COLUMNS) + 1
    col = (i % APP_COLUMNS) + ((row == max_row) ? last_row_padding : 1)

    [row, col] + app
  end
end.freeze

sitemaps.build do
  sitemap "tv", label: "TV Control Panel" do
    OpenHAB::DSL.items.equipments(Semantics::Television).sort_by(&:label).each do |tv|
      frame label: tv.label do
        switch item: tv.points(Semantics::Power).first, label: "Power"

        mute_item = tv.members.tagged("Mute").first
        setpoint item: tv.points(Semantics::SoundVolume).first,
                 label: "Volume [%d %%]",
                 icon: {
                   "0" => "if:icomoon-free:volume-mute",
                   "#{mute_item.name} == ON" => "if:icomoon-free:volume-mute2",
                   "< 9" => "if:icomoon-free:volume-low",
                   "< 13" => "if:icomoon-free:volume-medium",
                   ">= 13" => "if:icomoon-free:volume-high",
                   :default => "if:icomoon-free:volume-mute"
                 }

        application_item = tv.members.tagged("Application").first
        buttongrid item: application_item, buttons: APPLICATIONS

        rc_item = tv.members.tagged("RC").first
        buttongrid item: rc_item,
                   buttons: [
                     [1, 1, "BACK", "Back", "iconify:carbon:return"],
                     [1, 2, "HOME", "Menu", "iconify:ep:menu"],
                     [1, 3, "YELLOW", "Search", "material:search"],
                     [2, 2, "UP", "Up", "iconify:mingcute:up-fill"],
                     [4, 2, "DOWN", "Down", "iconify:mingcute:down-fill"],
                     [3, 1, "LEFT", "Left", "iconify:mingcute:left-fill"],
                     [3, 3, "RIGHT", "Right", "iconify:mingcute:right-fill"],
                     [3, 2, "ENTER", "Enter", "material:adjust"]
                   ]

        buttongrid item: tv.points(Semantics::Player).first,
                   buttons: [
                     [1, 1, "REWIND", "Rewind", "iconify:mingcute:fast-rewind-fill"],
                     [1, 2, "PAUSE", "Pause", "iconify:mingcute:pause-fill"],
                     [1, 3, "PLAY", "Play", "iconify:mingcute:play-fill"],
                     [1, 4, "FASTFORWARD", "Fast Forward", "iconify:mingcute:fast-forward-fill"]
                   ]

        switch item: tv.members.tagged("Timer").first, label: "Timer", icon: "time",
               mappings: {
                 "0" => "X",
                 "2" => "2",
                 "5" => "5",
                 "10" => "10",
                 "30" => "30"
               }

        switch item: tv.points(Semantics::TVLock).first,
               label: "[RB(|input.length > 2 ? Time.parse(input).to_i.seconds.to_human(long: false) : ''):%s]",
               icon: "lock",
               mappings: {
                 "0" => "OFF",
                 "10 min" => "10m",
                 "30 min" => "30m",
                 "60 min" => "1h",
                 "4 h" => "4h",
                 "12 h" => "12h"
               },
               value_color: { "!=NULL" => "red" }
      end
    end
  end
end

Note: The Android App doesn’t yet support Iconify / Material icons, but I have a PR for that.

In the mean time, I’m running a custom build version on my phone.

I believe iconify is supported in the IOS app, at least the beta version one.

3 Likes

@JimT: as usual, great stuff!

Wonderful

That’s correct. I don’t believe it supports buttongrid though :frowning:

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.