[SOLVED] Power control from TV?

And so I do (or should I post this as a linked topic?):

You need: 1 old USB cable (Plug type A to whatever), something that allows you to attach cables to the pin header of the RPi (like female pin headers or an old ribbon cable with connector), 2 resistors of about 270Ohm (240 Ohm is also ok, not much less, a bit more should be ok), 1 opto-isolator**, soldering tools. Optional: Lots of Heat shrink tubing.
For the opto-isolators, I chose PC817 DIL4, mainly because I got them for cheap shipping from EBay and because of the form factor that allows them to be soldered into the cable.

  1. Cut the whatever side of the USB cable of. You will see 4 small cables, red, black and 2 other colors. Cut the 2 other colors off and tug them away in a way that they don’t short-circuit.
  2. Solder one of the resistors to the red cable.
  3. Solder the other side of the resistor to the anode of the opto-isolator. For the PC817, this will be the pin marked with a dot. Don’t forget to but heatshrink on the cable before so you can cover the soldered parts afterwards.
  4. Solder the black cable to the cathode of the opto-isolator. For the PC817, this is the Pin next to the Anode. Don’t forget to but heatshrink on the cable before so you can cover the soldered parts afterwards.
    5***. Solder the other resistor to the collector of the opto-isolator. For the PC817, this will be the pin oppposite of the anode.
  5. Attach cables and connectors such that you can hook up the emitter to Pin 6 (GND) of the RPi and the resistor on the collector to Pin 5 (GPIO 3).
    (7. Cover in heatshrink.)

Now, as soon as your TV puts 5V on it’s USB port (I can confirm for my Samsung TV that it does not when in standby), GPIO3 will be connected to GND. If the RPi is in halt state (e.g. from the shutdown menu), it will start. When it is started, the following python script will check the GPIO and react on TV state changes (in the example, stop any player if the TV is switched on.)

#!/usr/bin/env python2.7
import time
import RPi.GPIO as GPIO
import json,requests

GPIO.setmode(GPIO.BCM)
GPIO.setup(3, GPIO.IN)

TVOff = GPIO.HIGH
TVOn = GPIO.LOW

tvState = GPIO.input(3)

def stopPlayers():
  response = requests.post(
        'http://localhost:80/jsonrpc', data=json.dumps({ "method": "Player.GetActivePlayers", "jsonrpc": "2.0", "id": 1, }), headers={'content-type': 'application/json'}).json()
  for result in response["result"]:
    stopPlayer(result["playerid"])

def stopPlayer(id):
  print("Stopping player "+str(id))
  requests.post(
        'http://localhost:80/jsonrpc', data=json.dumps({ "method": "Player.Stop", "params": {"playerid": id}, "jsonrpc": "2.0", "id": 1, }), headers={'content-type': 'application/json'}).json()

while 1:
  lastTvState = tvState
  tvState = GPIO.input(3)

  if lastTvState==TVOn and tvState==TVOff:
    print('TV switched off')
    try:
      stopPlayers()
    except Exception as e:
      print(e)
  elif lastTvState==TVOff and tvState==TVOn:
    print('TV switched on')

  time.sleep(0.1)

To get the code running, install necessary packages as follows:

sudo apt-get install python-pip python-dev build-essential
sudo pip install rpi.gpio

Save code as /home/osmc/stoponTVoff.py and put

/home/osmc/stoponTVoff.py > /tmp/stoponTVoff.log &

into /etc/rc.local before the exit line. (Or write a propper systemd script.)

** You do not necessarily need an opto-isolator. You could alternatively use a voltage divider and a transistor. However, this requires more parts and it is not so much “in series”, so it is harder to just solder it into a cable, and it is less save in general.
Even easier, you can connect the grounds and just connect the voltage divider to a GPIO. It will then be high when the TV is turned on. However, the latter solution will not allow you to turn on a halted RPi by turning on the TV.
*** Technically, the resistor in 5. is not necessary for what we are doing. However, if you hook the cable to a pin that is set to output-high for some reason, it may damage the RPi if we don’t have it. Note also that this only ensures the maximum current of the pin. If you draw a lot of current from the other GPIOs, you may still overload your power rail, so always keep your shit together when using the GPIOs. If they are set to input, as the script above does, you are save anyway.

2 Likes