Philips Android TV

Hello,

I want to control Philips Android TV via adb and exec binding.

I can get screen status with such script:

#!/bin/bash
adb kill-server &> /dev/null
adb connect 192.168.2.247 &> /dev/null
sleep 1 &> /dev/null
if adb shell dumpsys power | grep -q 'Display Power: state=OFF'; then
	echo "OFF"
else
	echo "ON"
fi

I can switch it on and off with:

#!/bin/bash
adb kill-server &> /dev/null
adb connect 192.168.2.247 &> /dev/null
sleep 1 &> /dev/null
if adb shell dumpsys power | grep -q 'Display Power: state=OFF'; then
	adb shell input keyevent 26
else
	echo "Display is already on"
fi
#!/bin/bash
adb kill-server &> /dev/null
adb connect 192.168.2.247 &> /dev/null
sleep 1 &> /dev/null
if adb shell dumpsys power | grep -q 'Display Power: state=ON'; then
	adb shell input keyevent 26
else
	echo "Display is already off"
fi

I’m new to OpenHab, could you help me to create switch for it?

Look at the Exec Binding wiki page

And executeCommandLine action

Be aware if you installed using apt-get OH is running as a limited user. The openhab user must have permission to read, write, and execute the scripts and everything in the scripts and any resources used by the script. If root is required the openhab user needs to be added to sudoers.

I’m looking to control my Philips TV too. What’s “adb”?

Means Android Debug Bridge. Tool to debug Android apps at low level.

Any hint how to install that to run your scripts?

You can bind the scripts to an item with the exec binding like

Switch HAB_Restart	"openHAB RESTART"	{ exec="ON:/etc/init.d/openhab restart,OFF:"}	
Switch RASPI_Restart	"PI RESTART"	                { exec="ON:reboot"}

e.g. I do bluetooh presense detection by:

Switch	BT_Status	"AtHome  (BT)"	<bluetooth> { exec="<[./bin/bt.sh 2:60000:REGEX((.*?))]" }

and the script looks like:

#!/bin/bash

#1=Mark, 2=Diane, 3=Nik
case $1 in
   1) MAC="11:43:7C:8B:C0:ED" ;;
   2) MAC="11:F4:6F:76:2A:12" ;;
   3) MAC="00:22:33:44:55:66" ;;
esac

if /usr/bin/l2ping -c 1 $MAC &> /dev/null
   then
      echo "ON"
   else
      echo "OFF"
fi

The item executes the .sh and then receives the status from the script.

A seconds approach is to post an item update with curl from your script:

curl -s --header "Content-Type: text/plain" --request POST --data "123" http://localhost:8080/rest/items/item_name

@GeertVc I have now adb, it’s able to connect, but any other command reports “device unknown” or any other errors. do you have an idea?
In addition I noticed that it’s not possible to connect to the TV when it’s powered of. So how are you able to switch it on when the TV is off?

I did some research on general control / binding. I foudn a Java imlementation of the anymote protocol, but it’s not able to connect to the device. Maybe it’s told. Do you have additional resources.

I was able to connect TV via ADB, you have to enable ADB connection on the TV. The problem is that adroid devices has 2 types of sleep mode - Sleep and Deep Sleep - in sleep mode you have only screen switch of, in deep sleep - network interfaces are disconnected. I tried to rub a script on raspberry that connect to the tv every 4 mins and pings some host outside the tv, to keep it out of deep sleep - but this didn’t work. In several hours, some times in serveral minutes device goes to deep sleep and I can switch it on only with remote. May be some one has better idea how to keep it out of sleep with screen off.

I must say that I don’t have experience (yet) with the binding you’re using, so I’ll be of little to no help in that case.

Coming back on your story: It’s not the intention of a customer to run adb on a Philips TV set. So, unless you find the correct option in the settings menu of your Android TV (which I think you won’t), you will not be able to connect through adb on your television. You can compare it with smartphones: unless your smartphone is “rooted”, you’re not able to modify anything towards the system files through adb. And if you “root” your device, the warranty is in most (if not all) cases voided.

Regarding switching on or off your TV: also there, it depends on how “off” your TV is. If it’s in standby (there are different levels of standby in such a set, but to the customer it’s all “standby”), then you should be able to switch on or off the set. Else, (that is, really off) obviously not.

Another possibility to control your Philips TV is to use the jointspace binding. jointSpace has been implemented into the Philips TV’s several years ago, to allow people to use the jointSpace API to control the TV set from outside in a (quite) limited way. Things like changing volume, ambilight, and so on… See the jointSpace binding for more information and the jointSpace web site for information about jointSpace itself. In the current jointspace implementation, only the API level 1 is supported, while the Philips TV’s are now already at API level 5 (or even possibly 6, I’m not sure). Since the jointspace binding is not maintained any more for quite a while, you’ll have to adapt the API level from 1 to 5 (or 6) in the binding and recompile it yourself. I did it myself a while back and I do remember it was quite a hassle to get openHAB compiled on a Linux machine (I did have problems with Maven and so on…). So, it’ll be a kind of an adventure trip I’m afraid…

Thanks @GeertVc. Just to clarify: I try to run dab on the raspberry together with OH2.
As far as I know jointspace is no longer supported with the new Philips TVs, because it’s not part of android TV. For thus the jointspace binding doesn’t has any function. The adb daemon is able to connect, but I’m not able to send any other command.
I couldn’t find any setting in the menu to differ between sleep and deep sleep. If your scripts are working youd had to disable the deep sleep - did you?

@Alexey_Levashev: Where could I enable the adb connection. Once I saw a message on the TV and confirmed that the app is allowed to connect and to remember that setting. Is there anything required in the android settings? Is there a sleep mode setting in the android settings?

@markus7017 No, there are no other places to switch it on, but still you’ll have an issue with power off network interfaces - so adb is useless until we’ll find a way to keep tv awake with switched off screen. Anyway - my steps to connect are below:

Power on the TV, check it’s IP in the network, login in to Raspberry as root

adb kill-server
adb connet XXX.XXX.XXX.XXX <- IP of the TV
adb shell

If you are able to log in to shell - then you could switch it off/on with my script above in the first message.

@Alexey_Levashev I still get “error device offline” event adb says "connected to "
Is there a PIN or something like that. One time I saw a screen of the TV to authorise USB debug and confirmed, but the screen never appeared again. Do you know if there is somewhere an option in the android settings?

pi@raspi ~ $ adb kill-server
pi@raspi ~ $ adb connect 192.168.6.165
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
connected to 192.168.6.165:5555
pi@raspi ~ $ adb shell
error: device offline
pi@raspi ~ $

@Alexey_Levashev - could you pls assist in how you got ADB installed - or which platform you are using as such?

I am looking similarly for controlling my Philips Android TV.

Cheers and thanks
Karsten

Sorry for late reply. This ADB function is very unstable. First of all - I suggest to try to run as root, not as pi user. And also try to restart TV - just power off from the 220V and power it on again. I’ve read some links on adb offline, but this function is still unstable for me.

Try to Google ADB - you have to have adb installed on pi.

yep. I had ADB installed, running with root privileges; in between I installed an SW update on the TV - so a new chance to try and let you know.

Hi @Alexey_Levashev
still working on controlling my TV

Current status:

However, problem with the POWER key remains: it sends the TV to deep sleep, no matter if lan or wlan, you can’t turn the TV on by using ADB.

I saw that the TV has a setting for WakeOnWLAN. I’ll try that, but would expect the same problem. The problem is that they key 26 put the TV in deep sleep rather than standby.

Any updates from your side?

#!/bin/bash

ptv_ip="192.168.1.20"

if adb devices | grep -q $ptv_ip; then
  echo Already connected toTV@ $ptv_ip
else
  echo Connecting to TV@$ptv_ip
  adb kill-server &> /dev/null
  adb connect $ptv_ip &> /dev/null
  sleep 1 &> /dev/null
fi

if adb devices | grep -q $ptv_ip; then

  case $1 in
    "status")
      if adb shell dumpsys power | grep -q 'Display Power: state=ON'; then
        echo "ON"
      else
        echo "OFF"
      fi;;
      
    "on")
      if adb shell dumpsys power | grep -q 'Display Power: state=ON'; then
        echo "TV is already ON"
      else
        adb shell input keyevent 26
      fi;;

    "off")
      if adb shell dumpsys power | grep -q 'Display Power: state=OFF'; then
        echo "Display is already OFF"
      else
        adb shell input keyevent 26
      fi;;
  
    "hdmi1")      
    	adb shell input keyevent 243
    	echo "HDMI1";;
    	
    "hdmi2")      adb shell input keyevent 244;;
    "hdmi3")      adb shell input keyevent 245;;
    "hdmi4")      adb shell input keyevent 246;;
    "composite1") adb shell input keyevent 247;;
    "composite2") adb shell input keyevent 248;;
    "component1") adb shell input keyevent 249;;
    "component2") adb shell input keyevent 250;;
    "vga")        adb shell input keyevent 251;;

  esac

else
  echo Unable to connect to TV@$ptv_ip
fi

@Alexey_Levashev: great progress!

A) ADB for raspi.

The version 1.0.31 you could find precompiled on various pages is to old (lack of security features) to connect to Android 5.x.

Here you find version 1.0.35 which works fine for me


and do a

sudo cp add-armhf and copy to /usr/bin/adb

B) Prevent deep sleep
I used the TV setting to enable a sleep timer 5 min
TV went off, manuel ON using the remote, but
when I run my script “philtv_control.sh off” afterwards the network interface stays up (verified by ping), so
another “philtv_control.sh on” turns the TV on again! verified multiple times.

Maybe the TV goes to suspend and not deep sleep once you used the sleep timer of the TV.

Give it a try.

Still need to manage that TV turns on HDMI1 - the add key events doesn’t do that.
Br, Markus

@Alexey_Levashev - made it

After a lot of tries and experiments sending keys with ADB I found the way to do both
a) send several specific keys including power and sleep
more codes can be found here:
https://developer.android.com/reference/android/view/KeyEvent.html#KEYCODE_AVR_POWER

b) wakeup the TV
For this you need to

  • enable Wake-on-LAN in the TV settings
  • send a WOL packet at that time you want to power on the TV
  • wait until network interface is available (using pings)
  • and then send the Power Key by ADB
    that’s it!!

Here’s my script (requires a compiled version of ADB and the package etherwake).

Then you could do tv_control.sh --help or
tv_control.sh on

the script supports multiple devices, just select the id as 2nd parameter
tv_control.sh on 2
1=Philips TV
2=FireStick

Before running the script you need to edit

tv_ip="192.168.6.XX"
tv_mac="XX:XX:6B:A9:CC:4D"
fire_tv_ip=“192.168.6.YY”

At least my Philips doesn’t respond to HDMIxx key, For that I use a hack: press Sources, press Home and x times down + ok.- what a petty:confounded:

I integrate into OH rules by
logInfo(“AVR”, " switch to TV")
executeCommandLine("/usr/share/openhab2/bin/philtv_control.sh tv", 15000)
or
logInfo(“AVR”, " switch TV off")
executeCommandLine("/usr/share/openhab2/bin/philtv_control.sh sleep 1", 15000)
executeCommandLine("/usr/share/openhab2/bin/philtv_control.sh sleep 2", 15000)

This also works with Alexa using the HUE emulation :slight_smile:

Please let me know if it works.

#!/bin/bash
#
# requires
# - compiled version of adb under /usr/bin
# - apt-get install etherwake
#
function e {
	echo $1 >> $log
}  

function adb_start {
	e Starting ADB Daemon...
	adb start-server >> $log
}

function adb_kill {
	adb kill-server >> $log
	e "ADB Daemon killed."
}

function adb_connect {
	if sudo adb devices | grep -q $uri; then
		e "Already connected to $uri"
	else
		# Connect to device, if failed exit script
		e "Connecting to $uri"
		#adb_kill
		adb connect $uri >> $log
		device_status
		if [ "$dev_status" == "ON" ]
		then
			sleep 2 &> /dev/null		# for timing
			display_status
		fi
	fi
}


# device_status: returns the device/connection status into dev_status ("ON"/"OFF")
function device_status {
	e "Check device status for $uri..."
  	if adb devices | grep -q $uri; then
  		dev_status="ON"
      else
		dev_status="OFF"
	fi
	e "Device Status=$dev_status"
}

function display_status {
	e "Check display status for $uri..."
	if adb -s $uri shell dumpsys power | grep -q 'Display Power: state=ON'; then
		dsp_status="ON"
    else
    	dsp_status="OFF"
    fi
	e "Display Status=$dsp_status"
}

function sendkey {
	e "Send Key $1"
	adb -s $uri shell input keyevent $1 >> $log
}

function tv_on {
   	device_status
   	display_status
	if [ "$dev_status" == "OFF" ]
	then
		#wakeup the device
		wakeonlan $tv_mac
		until ping -c1 $tv_ip &> $log; do :; done
		e "sleep 5sec"
		sleep 5
		adb_connect
		sendkey 26		# Power Button
   		device_status
	   	display_status
	fi
	if [ "$dev_status" == "OFF" ]
	then
		sendkey 26		# Power Button
	else
		sendkey 170		# TV Button
	fi
}

function presskey {
local keycode

	e "Press key '$1'"
	key1=$(($1 / 10))
	key2=$(($1 % 10))
	e "Key1='$key1', Key2='$key2'"
	if [ $key1 -gt 0 ]; then
	case "$key1" in
		"0") keycode=7;;
		"1") keycode=8;;
		"2") keycode=9;;
		"3") keycode=10;;
		"4") keycode=11;;
		"5") keycode=12;;
		"6") keycode=13;;
		"7") keycode=14;;
		"8") keycode=15;;
		"9") keycode=16;;
	esac
	sendkey $keycode
	fi

	case "$key2" in
		"0") keycode=7;;
		"1") keycode=8;;
		"2") keycode=9;;
		"3") keycode=10;;
		"4") keycode=11;;
		"5") keycode=12;;
		"6") keycode=13;;
		"7") keycode=14;;
		"8") keycode=15;;
		"9") keycode=16;;
	esac
	sendkey $keycode
}

function usage {
	echo
	echo "Usage: tv_control.sh <command> [<device id>[log | trace | debug]]"
	echo
	echo "Valid commands:"
	echo "	status:  return device status - ON/OFF"
	echo "	on:      switch device ON"
	echo "	off:     switch device OFF"
	echo "	sleep:   switch device to sleep mode (you have to check if sleep or soft_sleep works with your device)"
	echo "	suspend: switch device to soft-sleep mode (you have to check if sleep or soft_sleep works with your device)"
	echo "	resume:  (try to) wakeup device (doesn't work if device is powered off)"
	echo "	ping:    keep network interface device online - prevent power down while sleeping"
	echo "	avr:     speical: switch to HDMI1 on Philips TV to select AVR"
	echo "	see script code for key commands (simulate remote keys)"
	echo
	echo "Device IDs:"
	echo "	1: TV@$tv_ip:$port"
	echo "	2: Fire-TV@$fire_tv_ip:$port"
	echo "	Default IP=$tv_ip; Default Port=$port (see script)"
	echo
	echo "Debugging":
	echo "	log      Enable logging to stdout"
	echo "	trace    Enable ADB trace (output will be redirected to logfile)"
	echo "	debug    Enable ADB debugging (output will be redirected to logfile)"
	echo
	echo "Examples:"
	echo "	sudo ./tv_control.sh on (uses default IP $tv_ip - see script)"
	echo "	sudo ./tv_control.sh home (send HOME key to device)"
	echo "	sudo ./tv_control.sh sleep 192.168.1.1"
	echo
	echo "Note:"
	echo "	Logfile: $log"
	echo "	The scripts writes log messages to $log - change $$log in script if you don't have privileges there"
	echo
}

#
log_sw="no"   # no stdout
log="/var/log/openhab2/tv_control.log"
#log="/dev/stdout"
#

#
# IP address and port for devices
#
tv_ip="192.168.6.XX"
tv_mac="XX:XX:6B:A9:CC:4D"
fire_tv_ip="192.168.6.YY"
dev_status="n/a"
dsp_status="n/a"
port="5555"
tv_key=""
#export >> $log	# dump environment, e.g. user (privileges)

if [ "$1" == "" ]
then
	usage
	exit 1
fi
if [ "$1" == "--help" ]
then
	usage
	exit 1
fi


#
# tv_control
#
echo > $ log  # clear log

cmd="$1"
shift
if [ "$cmd" == "presskey" ]
then
	e "Press key '$1'"
	tv_key="$1"
	shift
fi

# build URI from device ip and port (5555)
case $1 in
	"1") ip=$tv_ip;;          # TV
	"2") ip=$fire_tv_ip;;     # Fire-TV
	"")  ip=$tv_ip;;          # default = TV
esac
shift
uri="$ip:$port"
case $1 in
	"log")    log="/dev/stdout"; log_sw="yes";;
	"trace")  export ADB_TRACE=1;;
	"debug")  export ADB_TRACE=1;;
esac

# If not yet connected start ADB server and connect to device
# maybe it needs some more error handling
e "TV Control (IP=$uri): $1"
if [ "$cmd" == "check" ]
then
	device_status
	display_status
	echo "$dev_status"
	exit
fi
adb_connect
if [ "$device_status" == "OFF" ]
then
	e "Unable to connect to device."
	e "ADB Log:"
	if [ "$log_sw" == "yes" ]
	then
		cat "$log"
	fi
	exit 1
fi

#
# process command
#	
 case "$cmd" in
    "status")	# Display status
    	display_status
		echo "$dsp_status";;
     
    "on")
      if adb -s $uri shell dumpsys power | grep -q 'Display Power: state=ON'; then
        e "Display is already ON"
      else
        tv_on
      fi
      echo "ON";;

    "off")
      if adb -s $uri shell dumpsys power | grep -q 'Display Power: state=OFF'; then
        e "Display is already OFF"
      else
        sendkey 26
      fi
      echo "OFF";;

	"ping")
		device_status
		if [ "$dev_status" == "ON" ]
		then
		 	sendkey 223
			echo "ON"
		else
			echo "OFF"
		fi;;

    "tv")
		tv_on
		dev_status
		echo "$dev_status"
    	;;

	"avr")
		tv_on
		adb -s $uri shell "input keyevent 178 && input keyevent 122 && input keyevent 122 && input keyevent 20 && input keyevent 20 && input keyevent 20 && input keyevent 20 && input keyevent 20 && input keyevent 66";;

	"power")      sendkey 26;;		# Power Button
	"sleep")      sendkey 223;;		# Sleep Button
	"suspend")    sendkey 276;;		# Soft Sleep Button
	"resume")     asendkey 224;;	# Wakeup Button	
	"pairing")    sendkey 225;;		# Pairing Button
	"settings")   sendkey 176;;		# Settings Button
	"presskey")   presskey $tv_key;;

    "input")      sendkey 178;;		# Source TV
    "sat")        sendkey 237;;		# Source SAT
    "hdmi1")      sendkey 243;;		# Source HDMI1
    "hdmi2")      sendkey 244;;		# Source HDMI2
    "hdmi3")      sendkey 245;;		# Source HDMI3
    "hdmi4")      sendkey 246;;		# Source HDMI4
    "composite1") sendkey 247;;		# Source Compsite1
    "composite2") sendkey 248;;		# Source Compsite2
    "component1") sendkey 249;;		# Source Component1
    "component2") sendkey 250;;		# Source Component2
    "vga")        sendkey 251;;		# Source VGA
    "text")       sendkey 233;;		# Source Video-Text

    "home")       sendkey 3;;		# Home Button
    "menu")       sendkey 82;;		# Menu Button
    "back")       sendkey 4;;		# Back Button
    "top")        sendkey 122;;		# Top Button
    "end")        sendkey 123;;		# End Button
    "enter")      sendkey 66;;		# Enter Button
    "up")         sendkey 19;;		# UP Button
    "down")       sendkey 20;;		# DOWN Button
    "left")       sendkey 21;;		# LEFT Button
    "right")      sendkey 22;;		# RIGHT Button
    "sysup")      sendkey 280;;		# SysUp Button
    "sysdown")    sendkey 281;;		# SysDown Button
    "sysleft")    sendkey 282;;		# SysLeft Button
    "sysright")   sendkey 283;;		# SysRight Button
  
    "blue")       sendkey 186;;		# Blue Button
    "green")      sendkey 184;;		# Green Button
    "red")        sendkey183;;		# Red Button
    "yellow")     sendkey 185;;		# Yellow Button
    "move_home")  sendkey 122;;		# MoveHome Button
    "search")     sendkey 84;;		# Search Button

	"volup")      sendkey 24;;		# VolUp Button
	"voldown")    sendkey 25;;		# VolDown Button
	"mute")       sendkey 164;;		# Mute Button

    "lastch")     sendkey 229;;		# LastChannel Button

	"kill")       adb_kill;;		# Kill ADB
	"start")      adb_start;;		# Start ADB

	*)            echo "Unknown command: $cmd"; exit;;
esac

exit 0

1 Like

Nice work @markus7017 many thanks for sharing. Do you know if there is a way to know through adb which app has focus on the TV? getCurrentFocus should be a class which returns the name of the current focused app, I just don’t quite know how to implement this in adb/bash as per your examples.

My thought is so I can know if Netflix is running, or some other app, and have that determine some lighting states.

Had a crack at getting this to work. See below to create an output of the current running app process name. Using rules in OH it won’t be hard to define translations from the raw output. This script also assumes an adb connection has already been made with adb connect <yourip and port>. I haven’t had time to find out the best way to create this connection in python first. I’ll update it if I get time, or if someone else wants to add this information.

androidTVFocus.py

#!/usr/local/bin/python

"""
Communicate with an Nvidia ShieldTV device via ADB over a network.
ADB Debugging must be enabled.
Example output strings are below. The .replace options shorten these to the app name alone. Shown in ()
com.plexapp.android (plex)
com.google.android.leanbacklauncher (leanbacklauncher)
com.netflix.ninja (netflix)
com.google.android.youtube.tv (youtube)
"""

import re
import sys
import subprocess

def execute_shell(command, working_directory=None, stdout=None, stderr=None):
    p = subprocess.Popen([command], cwd=working_directory, shell=True, stdout=stdout, stderr=stderr)
    if stderr:
        stdout, stderr = p.communicate()
        return stdout, stderr
    elif stdout:
        output = p.stdout.read()
        return output
    else:
        p.wait()

# Get current activity and grab package name from it: adb shell dumpsys window windows | grep -E 'mCurrentFocus'
activity_info = execute_shell("adb shell dumpsys window windows | grep -E 'mCurrentFocus'", stdout=subprocess.PIPE)

pattern = 'u0 (.*)\/.*\.(.*)}'

try:
    app_name = re.search(pattern, activity_info).group(1).strip().replace(".", "").replace(" ", "").replace("com", "").replace("ninja", "").replace("android", "").replace("google", "").replace("tv", "").replace("app", "")
except Exception:
    app_name = ""

print(app_name)

Item:
String androidApp "Current App [%s]" <app>

Thing:
Thing exec:command:androidApp [command="/usr/bin/python /etc/openhab2/scripts/androidTVFocus.py", interval=900, timeout=30, autorun=true]

Sitemap:
Text item=androidApp

1 Like