HABPanelViewer Automation (Tablet screen on/off, brightness)

Targets
Automate a HABPanelViewer Tablet to:

  • show HABPanel/BasicUI on default
  • switch display between dim/bright on action
  • completely turn off display e.g. at night

Make all this robust so that even a tablet restart ends in desired state again.

It isn’t so difficult, but there are many small things to consider, so I decided to write this tutorial, so even I don’t forget it.

Tested using Android 5.4, but should work with more recent versions, too.

Tablet Configuration
In Android Settings -> Display set:

  • Display brightness level to minimal
  • Sleep to minimal time (15 seconds in my case)

If you also want to use tablet without being plugged in, maybe disable Android Settings -> Battery -> Standby intelligent power saving so chances of W-LAN connection being dropped are lower

OpenHAB Configuration
items/Tablet.items

String  Tablet_Command        "Command tablet"
Contact Tablet_Usage          "Usage (last 5 s) [%s]"
Contact Tablet_Screen         "Screen on [%s]"
Switch  Tablet_ScreenTarget   "Screen desired state [%s]"
Dimmer  Tablet_BrightnessLow  "Brightness low"
Dimmer  Tablet_BrightnessHigh "Brightness high"

rules/Tablet.rules

rule "Turn on/off tablet depending on lights"
when
    Item GP_LightsSwitch changed // modify to use your own
then
    Tablet_ScreenTarget.sendCommand(GP_LightsSwitch.state.toString)
end

rule "Change brightness of tablet depending on usage"
when
    Item Tablet_Usage changed
    or Item Tablet_BrightnessLow changed
    or Item Tablet_BrightnessHigh changed
then
    if(Tablet_Usage.state == CLOSED) {
        Tablet_Command.sendCommand("SET_BRIGHTNESS " + Tablet_BrightnessHigh.state.toString)
    } else {
        Tablet_Command.sendCommand("SET_BRIGHTNESS " + Tablet_BrightnessLow.state.toString)
    }
end

rule "Turn on/off tablet depending on desired state"
when
    Item Tablet_ScreenTarget received command
then
    Thread::sleep(50) // allow values to settle
    if(Tablet_ScreenTarget.state == ON) {
        Tablet_Command.sendCommand("SCREEN_ON")
        createTimer(now.plusSeconds(2))[|Tablet_Command.sendCommand("KEEP_SCREEN_ON")]
    } else {
        Tablet_Command.sendCommand("ALLOW_SCREEN_OFF")
        createTimer(now.plusSeconds(2))[|Tablet_Command.sendCommand("SCREEN_DIM")]
    }
end

rule "Turn on/off tablet if it behaves the wrong way (e.g. after tablet restart)"
when
    Item Tablet_Screen changed
then
    if(Tablet_Screen.state == CLOSED && Tablet_ScreenTarget.state == OFF || Tablet_Screen.state == OPEN && Tablet_ScreenTarget.state == ON)
    {
        Tablet_ScreenTarget.sendCommand(Tablet_ScreenTarget.state.toString)
    }
end

sitemaps/tablet.sitemap (for debugging purposes)

sitemap tablet label="Tablet debugging" {
	Frame label="Tablet Status" {
		Text item=Tablet_Usage
		Text item=Tablet_Screen
	}
	Frame label="Command" {
		Switch item=Tablet_Command mappings=["KEEP_SCREEN_ON"="Keep on", "SCREEN_ON"="On"]
		Switch item=Tablet_Command mappings=["ALLOW_SCREEN_OFF"="Allow Off", "SCREEN_DIM"="Dim"]
		Text icon=none
		Switch item=Tablet_Command mappings=["RESTART"="RESTART"]
	}
	Frame label="Screen" {
		Switch item=Tablet_ScreenTarget
		Text icon=none
		Slider item=Tablet_BrightnessLow
		Slider item=Tablet_BrightnessHigh
	}
}

HABPanel configuration
Preferences -> Connection

  • [x] Track Browser Connection

Preferences -> User Interface

  • [x] Show on lock screen
  • [x] Hide Soft Keys

Preferences -> Command Item: Tablet_Command

Preferences -> Value Reporting -> Screen

  • [x] Toggle openHAB contact item depending on device screen state
  • Screen State Contact: Tablet_Screen

Preferences -> Value Reporting -> Usage

  • [x] Toggle openHAB contact item when the app is actively used
  • Usage Contact: Tablet_Usage
  • Usage Timeout: 5 (seconds - the time you want your tablet to return to dim again)

… and done! Now openHAB is master to command your tablet.
Even when you unlock your tablet and change some Android settings - as long as HABPanelViewer is running in background, it will return to foreground when tablet tries to go to sleep (it will go to sleep but immediately woken up and show HABPanelViewer again) - so nothing can go wrong anymore!

Sitemap for debugging purposes:


Brightness values should be set once and ideally be persisted.

2 Likes

Very neat. This forms the basis of tablet control; you can combine this with motion / presence detection.

In each room I have motion sensors. The screen also brightens itself for a configurable amount of time when motion is detected.

Yeah, thanks. You can even combine it with a luminance sensor :wink:

great idea :slight_smile:

It does make me smile when I walk into a room and all the controls light up. :smiley:

was this tested with V2.x or V3? - im having one hell of a time getting 3.0 to work :frowning:
My tablet and phone works flawlessly with my 2.4 install… but 3.0 just wont recieve any commands…

It works with OpenHAB 3 … if you use latest (beta) Version 0.9.27pre of HABPanelViewer linked in first post of this topic: HABPanelViewer 0.9.26
Export your settings, uninstall Store version of that app and then you can install debug version.

There has been an incompatible change in REST interface of OpenHAB, thus requiring a new version.

updated a bit the code, somebody might find it useful

items/panel.items:

Group Panel
Group PanelScreen
Group PanelScreenTarget
Group PanelUsage
Group PanelBrightnessLow
Group PanelBrightnessHigh
Group PanelCommand
String  Corridor_Panel_Command        "Command Panel" (PanelCommand)
Contact Corridor_Panel_Usage          "Usage (last 5 s) [%s]" (PanelUsage)
Contact Corridor_Panel_Screen         "Screen on [%s]" (PanelScreen) 
Switch  Corridor_Panel_ScreenTarget   "Screen desired state [%s]" (PanelScreenTarget)
Dimmer  Corridor_Panel_BrightnessLow  "Brightness low" (PanelBrightnessLow)
Dimmer  Corridor_Panel_BrightnessHigh "Brightness high" (PanelBrightnessLow)

rules/panel.rules:

rule "Turn on/off panel depending on presense"
when
    Member of Panel changed
then
    val room = triggeringItem.name.split("_").get(0)
    val st = PanelScreenTarget.members.findFirst[ st | st.name == room + "_Panel_ScreenTarget" ]
    st.sendCommand(triggeringItem.state.toString)
end
rule "Change brightness of panel depending on usage"
when
    Member of PanelUsage changed
    or Member of PanelBrightnessLow changed
    or Member of PanelBrightnessHigh changed
then
    val room = triggeringItem.name.split("_").get(0)
    val usage = PanelUsage.members.findFirst[ usage | usage.name == room + "_Panel_Usage" ]
    val pc = PanelCommand.members.findFirst[ pc | pc.name == room + "_Panel_Command" ]
    val bh = PanelBrightnessHigh.members.findFirst[ bh | bh.name == room + "_Panel_BrightnessHigh" ]
    val bl = PanelBrightnessLow.members.findFirst[ bl | bl.name == room + "_Panel_BrightnessLow" ]
    if(usage.state == CLOSED) {
        pc.sendCommand("SET_BRIGHTNESS " + bh.state.toString)
    } else {
        pc.sendCommand("SET_BRIGHTNESS " + bl.state.toString)
    }
end
rule "Turn on/off panel depending on desired state"
when
    Member of PanelScreenTarget received command
then
    val room = triggeringItem.name.split("_").get(0)
    val st = PanelScreenTarget.members.findFirst[ st | st.name == room + "_Panel_ScreenTarget" ]
    val pc = PanelCommand.members.findFirst[ pc | pc.name == room + "_Panel_Command" ]
    Thread::sleep(50) // allow values to settle
    if(st.state == ON) {
        pc.sendCommand("SCREEN_ON")
        createTimer(now.plusSeconds(2))[|pc.sendCommand("KEEP_SCREEN_ON")]
    } else {
        pc.sendCommand("ALLOW_SCREEN_OFF")
        createTimer(now.plusSeconds(2))[|pc.sendCommand("SCREEN_DIM")]
    }
end
rule "Turn on/off panel if it behaves the wrong way (e.g. after panel restart)"
when
    Member of PanelScreen changed
then
    val room = triggeringItem.name.split("_").get(0)
    val ps = PanelScreen.members.findFirst[ ps | ps.name == room + "_Panel_Screen" ]
    val st = PanelScreenTarget.members.findFirst[ st | st.name == room + "_Panel_ScreenTarget" ]
    if(ps.state == CLOSED && st.state == OFF || ps.state == OPEN && st.state == ON)
    {
        st.sendCommand(st.state.toString)
    }
end

Group Panel is assigned to Presense switch (which in my case is affected by several items) in the rooms, where I have panels installed

With such approach, you’ll just need additional items, if you have multiple tablets

1 Like