Benutzer:Rstooks21/Kiosk UI

Aus FHEMWiki


Clock - Under Construction.svg This Page is Work in progress.


Kiosk UI

This is an approach to the dynamic creation of a Kiosk UI that can be used by anyone visiting the home. There will be multiple, small, possibly wall mounted Kiosk screens - one in each physical room. The Kiosk UI controls only the devices that are located in the same [FHEM] Room.

The Objective

To use the new FHEM Tablet UI (FTUI3) to create a tabbed design that allows the most important device controls to be shown by default and at the same time allow other devices to be controlled in as few clicks/screen touches as possible. The rooms selected for testing had some or all of:

  • Lighting (Shelly RGDW LED Controller and Shelly DImmer 2, defined to FHEM as Shelly devices)
  • Audio (Logitech Media Players defined to FHEM as SBPLAYER devices)
  • Heating (EQ3 MAX! WallMountedThermostat and RadiatorThermostat, defined as MAX devices)

With a simple call, the Kiosk screen displays the default screen, with tabs for other device control screens. The default screens are implemented in the following order:

  • Lighting first
  • If no Lighting, then Audio
  • If no Lighting or Audio, then Heating

This web address is intended to be used in a browser in Kiosk mode

http[s]://fhem-location:8083/fhem/kiosk/kiosk.html?room=Kitchen

The Panels

All the panels time out to the primary panel after 60 seconds of non use.

The Lighting Panels

Main Panel

The main Lighting Panel is a simple On/Off switch and dimmer slider. The single control will control all of the lights in the room equally

  • turning them all off or on
  • dimming all lights in proportion
An on/off switch and a slider used for dimming the lights
An FTUI3 Main Lighting control panel

Note the four tabs. The Lighting tab has further settings that can be adjusted.

Settings/Scene Selector Panel

Selecting the "Settings" tab allows the user to select a scene - a combination of light settings that have been previously saved (by the user in the Kiosk UI)

A grid of four buttons in a panel display
FTUI Grids and Buttons used to save and recall scenes

The light settings for all lights in the room are recalled by a short press to any of the buttons.

The current light settings for all lights in the room are stored as a scene by pressing and holding the relevant button. This causes the scene to be saved and the button to glow with the average light colour and intensity for all lights that are on.

The Details Panel

From the Scene Selector Panel it is possible to control every light in the room individually. The Details Panels are flexed to display up to three lights each with as many Panels as needed:

An on/off switch and four sliders in Red, Green, Blue and White
FTUI3 Switch and Sliders for RGBW control of a single led strip

The Audio Panel

The Audio Panel uses an IFRAME to embed the Logitech Media Server web interface into the panel. Only the player in the room can be controlled - the other players cannot be unless they are synchronised. This is a bit of a cheat as the facilities in FHEM to control the player and display album art are not used. But why reinvent?

A media player display with a second tab for heating control
The IFRAME containing the web interface at the top (90% height) and the two tabs at the bottom. One for the Music and a second for the Heating.

The Heating Panel

The Heating Panel prioritises control of the room's temperature using a Wall Mounted Thermostat, if one is available. If not, it is assumed that one of the Radiator Thermostats can be used and that all, if more than one, are linked together.

The heating screen just allows the setting of the temperature in the same room. None of the other room's temperatures may be set, nor can any "scenes" be set.

A dial with a gradient to show actual temperature and a needle to show desired temperature
An FTUI3 Compound Thermostat showing Actual and Desired Temperature

Prerequisites

The FTUI3 code, available from GITHUB should be downloaded and added to FHEM following the instructions here: https://github.com/knowthelist/ftui

Create an HTTPSRV address for the kioskUI:

define kioskUI HTTPSRV kiosk /opt/fhem/www/ftui Kiosk

Code

Kiosk HTML

The HTML is divided into three sections

The First Section

... in the <HEAD> reads in the FTUI3 code and META tags that configure it. This implementation choses not to use Toast messages

<!DOCTYPE html>
<html>

<head>
  <!--
    /* FHEM tablet ui - FTUI */
    /**
    * UI builder framework for FHEM
    *
    * Version: 3.0.0
    *
    * Copyright (c) 2015-2021 Mario Stephan <mstephan@shared-files.de>
    * Under MIT License (http://www.opensource.org/licenses/mit-license.php)
    * https://github.com/knowthelist/ftui
    */
    -->
  <script src="ftui.js"></script>

  <link href="ftui.css" rel="stylesheet">
  <link href="themes/ftui-theme.css" rel="stylesheet">
  <link href="favicon.ico" rel="icon" type="image/x-icon" />

  <!-- avoid 300ms delay on click-->
  <meta name="viewport" content="width=device-height, height=device-width, user-scalable = no, initial-scale = 1, maximum-scale = 1, minimum-scale = 1">

  <meta name="mobile-web-app-capable" content="yes">
  <meta name="toast_position" content="topLeft">
  <meta name="toast" content="0"> 
  <meta name="fhemweb_url" content="http://<your-url>:8083/fhem/">
  <meta name="refresh_interval" content="60">

  <!-- verbose level 0-4 -->
  <meta name="debug" content="0">

The Second Section

... also in the <HEAD> reads in the Kiosk support files

  <!-- SET UP THE KIOSK -->
  <title>KIOSK</title>
  <script src="./kiosk/light_class.js"></script>
  <script src="./kiosk/init.js"></script>
  <script src="./kiosk/light_functions.js"></script>
  <link href="./kiosk/kiosk_styles.css" rel="stylesheet"/>
  <!-- <link href="./kiosk/kiosk-theme.css" rel="stylesheet"> -->
  
  </head>

The Third Section

... defines the body.

This contains outlines of the Panels, ready for customisation by the JavaScript.

The body has a kiosk_onLoad() function - this is part of the Kiosk customisation and is called to customise the predefined panels once the outlines have been loaded

<body class="body" onload="kiosk_onLoad()">

The first tab defined is a clock. This should only ever be shown if there are no controllable devices in the room. It's included so that this is obvious (for instance if something has gone wrong with the Kiosk definition). There are also three clickable tabs in this panel. These serve two purposes:

  1. To allow the configuration to be manually checked when something has gone wrong.
  2. To allow the kiosk_onLoad() function to select the first panel for display using the FTUI App by triggering the onclick event.
<ftui-tab-view id="Clock">    
    <ftui-row class="kiosk-panel-row" style="height:100vh">
    <ftui-grid-tile row="1" col="1" shape="round" color="primary">
      <ftui-row >
        <ftui-clock format="ee" size="6"></ftui-clock>
        <ftui-clock format="DD" size="5"></ftui-clock>
      </ftui-row>
      <ftui-clock format="hh:mm" size="9"></ftui-clock>
    </ftui-grid-tile>
    </ftui-row>
    <ftui-row class="kiosk-tab-row">

      <ftui-grid-tile col="1" width="0.25" >
        <ftui-tab view="Clock" id="click-clock">
          <ftui-icon name="clock"></ftui-icon>
        </ftui-tab> 
    </ftui-grid-tile>
    <ftui-grid-tile col="2" width="0.25">
        <ftui-tab view="Player-Main" id="click-player">
          <ftui-icon name="music"></ftui-icon>
          <ftui-label>Music</ftui-label>
        </ftui-tab>
      </ftui-grid-tile>
      <ftui-grid-tile col="3"  width="0.25">
        <ftui-tab view="Heating-Main"  id="click-heating" >
          <ftui-icon name="fire"></ftui-icon>
        </ftui-tab>
      </ftui-grid-tile>
      <ftui-grid-tile  col="4" width="0.25">
        <ftui-tab view="Lighting-Main"  id="click-lighting">
          <ftui-icon name="lightbulb"></ftui-icon>
        </ftui-tab>
      </ftui-grid-tile>
      </ftui-row>
  </ftui-tab-view>

The next section defines the main panels for the Lighting,

<ftui-tab-view id="Lighting-Main">    
      <ftui-row class="kiosk-panel-row">
        <ftui-column width="25%">
          <ftui-button id="LightingPower"
                       value="off" fill="outline" shape="circle" states="on,off" color="gray"
                       @value-change='powerChange($event)'>
            <ftui-icon name="power-off"></ftui-icon>
          </ftui-button>
        </ftui-column>
        <ftui-column width="75%">
          <ftui-slider  id="LightingDimmer"
                        value="1" min="1" max="100"
                        color="white"
                        @value-change="dimmerChange($event)"
                        >
          </ftui-slider>
        </ftui-column>
      </ftui-row>
      <ftui-row id="Lighting-Tabs" class="kiosk-tab-row" >
        <ftui-column id="Lighting-Scenes-Tab" class="kiosk-tab-inactive">
            <ftui-tab class='kiosk-button' view="Lighting-Scenes" timeout="60">
              <ftui-icon name='cog'></ftui-icon>
              <ftui-label>Settings</ftui-label>
            </ftui-tab>
          </ftui-column>
      </ftui-row>
    </ftui-tab-view>

Heating

<ftui-tab-view id="Heating-Main" >
    <ftui-row id="Heating-Tabs"class="kiosk-tab-row" >
    </ftui-row>
    </ftui-tab-view>

and Audio

<ftui-tab-view id="Player-Main" >
      <ftui-row class="kiosk-panel-row">
      <iframe  id="Player-kiosk" src="" style="height:90vh;width:100vw;overflow:hidden;padding:0px;border:none;margin:0px"></iframe>
      </ftui-row>
      <ftui-row id="Player-Tabs" class="kiosk-tab-row">
      </ftui-row>
</ftui-tab-view>

The Scenes Tab and Success popup are also defined. At line 150, the tab selector for the first Lighting Detail Panel is also created:

<ftui-tab-view id="Lighting-Scenes">    
      <ftui-row class="kiosk-panel-row" style="gap:5em;">
        <ftui-grid margin="5" shape="round">
        <ftui-grid-tile row="1" col="1" width='1' height='1' class="kiosk-scene-button">
          <ftui-grid-header class='scene_header' id='scene1_header' color="medium">Scene 1</ftui-grid-header>
          <ftui-button id='scene1' style='box-shadow:0px 0px 10px 5px #B26464;border-radius:var(--grid-tile-border-radius);text-align:center;' fill="solid" color="medium" @hold="save_scene(this)" @click="show_scene(this)" class="kiosk-scene-button" >Press to Select</ftui-button>
        </ftui-grid-tile>
        <ftui-grid-tile row="1" col="2" width='1' height='1' class="kiosk-scene-button" >
          <ftui-grid-header class='scene_header' id='scene2_header' color="medium">Scene 2</ftui-grid-header>
          <ftui-button id='scene2' style='box-shadow:0px 0px 10px 5px #FF6464;border-radius:var(--grid-tile-border-radius);text-align:center;' fill="solid" color="medium"  @hold="save_scene(this)" @click="show_scene(this)" class="kiosk-scene-button"><p>Press to Select</p></ftui-button>
        </ftui-grid-tile>
        <ftui-grid-tile row="2" col="1" width='1' height='1' class="kiosk-scene-button">
          <ftui-grid-header  class='scene_header' id='scene3_header' color="medium">Scene 3</ftui-grid-header>
          <ftui-button id='scene3' style='box-shadow:0px 0px 10px 5px #64C9C9;border-radius:var(--grid-tile-border-radius);text-align:center;' fill="solid" color="medium"  @hold="save_scene(this)" @click="show_scene(this)" class="kiosk-scene-button"><p>Press to Select</p></ftui-button>
        </ftui-grid-tile>
        <ftui-grid-tile row="2" col="2" width='1' height='1' class="kiosk-scene-button">
          <ftui-grid-header  class='scene_header' id='scene4_header' color="medium">Scene 4</ftui-grid-header>
          <ftui-button id='scene4' style='box-shadow:0px 0px 10px 5px #1F6F3F;border-radius:var(--grid-tile-border-radius);text-align:center;' fill="solid" color="medium"  @hold="save_scene(this)" @click="show_scene(this)" class="kiosk-scene-button"><p>Press to Select</p></ftui-button>
        </ftui-grid-tile>
        <ftui-grid-tile row="3" col="1" width='2' height='0.1'>
          Long hold to set
        </ftui-grid-tile>
      </ftui-grid>
      </ftui-row>
      <ftui-row id="Lighting-Scenes-Tabs" class="kiosk-tab-row" >
        <ftui-column id="Lighting-Scenes-Back-Tab" class="kiosk-tab-active-back">
            <ftui-tab class='kiosk-button' view="Lighting-Main">
              <ftui-icon name='reply'></ftui-icon>
              <ftui-label>Go Back</ftui-label>
            </ftui-tab>
          </ftui-column>
        <ftui-column id="Lighting-Settings-Detail0-Tab" class="kiosk-tab-inactive">
            <ftui-tab class='kiosk-button' view="Lighting-Setting-Detail0"  timeout="60">
              <ftui-icon name='tasks'></ftui-icon>
              <ftui-label>Details</ftui-label>
            </ftui-tab>
          </ftui-column>
      </ftui-row>
    </ftui-tab-view>

    <ftui-label id="scene-success-click" @click='scene_success.open()' style="display:none"></ftui-label>
    <ftui-popup id="scene_fail" timeout="15" color="warning">
      <header>Failed To Save</header>
      <ftui-label>Failed to Save Scene</ftui-label>
    </ftui-popup>
    <ftui-popup id="scene_success" timeout="5">
      <header>Saved</header>
      <ftui-label>Scene Saved</ftui-label>
    </ftui-popup>

Kiosk JavaScript

Kiosk CSS

Improvements required

  1. The Heating Thermostat scales well for square displays, but other aspect ratios are not handled well.
  2. There is code duplication between this implementation and the FTUI3 App. This should be eliminated.
  3. The hard-coded timeouts should be <META> driven.
  4. Control of further devices, using the same principles should be possible.