Remotely turn on/off a connected TV

I am deploying a couple of Pis running Screenly OSE connected to normal LCD flat TVs used as monitors via their HDMI inputs. The displayed content is needed only during the working hours, (it is a social project in a community building I do for free), and I need to turn off the TVs when not used to save electric power for the hosting organization, the Pis can remain on and online the whole time.

My first idea is to cut-off the power to the TV set via a relay board that is connected to the Pi’s io ports.
I have made several such iot gadgets already, I use MQTT for the remote control, no problem with this part…

The problem is that no TV I know of ‘autoboot’ after reconnected to the power line, they need a separate turn-on signal sent from their remotes. This a problem also when an accidental power outage causes the TV to turn off, even after the power is restored, the TV needs to be turned on manually. In new models there is also a dead-man’s function that would automatically turn-off the TV after x hours of operation of not overruled manually, I hope this could be disabled (?)

Sending a ‘turn-on’ IR signal to the TV with my add-on board is an option, and it could also regularly reselect the HDMI input source on the TV set for being safe. (i could stick small plastic cover with an IR led inside on the TV’s IR sensor directly, this would also serve as blocking any outside IR signal of somebody messing with a remote), but the whole thing is getting too much complicated and my main concern is that how could I make this not depending on a particular TV model and manufacturer.

Do you guys have any advice how it could be done reliably, professionally?

I managed to find an easy solution using HDMI CEC signaling, luckily the Raspberry has the hardware for it already, and almost all modern TV sets also have CEC interface in their HDMI inputs.

Hi @matrix - glad you found a solution. Yes, we have some documentation for that here.

Your approach with CEC is probably the best approach for consumer grade monitors. Commercial monitors usually provide an RS232 interface for controlling the monitor. This is however rare in consumer grade monitors.

Do however note that if the power is off on the monitor when the Raspberry Pi reboots/boots, it will likely detect the wrong resolution.

Hi @vpetersson - I was able to setup a crontab to turn on and off my monitors. I have three screenly instances running and they are all supposed turn on and off at the same time, however, some days that is not the case. Two may fire up and one doesn’t. Sometimes one and two don’t. What do you think could be the reason for this?

@vpetersson - Also, I’m using balena.io to serve my deployment. Currently I had to individually add the cronjob onto each device. Is there a way I can add the cronjob into my build, so any future device I deploy from Balena.io will have the cronjob?

I believe you can simply create this on your Dockerfile… either as a CMD or a script file that gets copied over during build.

Cronjobs is not something that belongs in a Docker container (as it isn’t compatible with the dockerized world). As of the recent versions, we have introduced Celery, which is a worker. The proper way to implement this would be to add a Celery task that turns on/off the monitors.

Sorry I’m not familiar with Celery, please could you point me in the direction how to setup a task. Thanks!

Does this help?

https://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html

1 Like

Thanks for quick response. Will check on it.

Most of the Celery work in Screenly OSE can be found in this PR.

(tl;dr in a dockerized workload, you only run one process per container. Cron is designed for a traditional system. The “modern” way to replace Cron is to use a pub/sub-style system where you schedule a task (e.g. turn tv off) from a web interface or a timer and a “worker” picks up on this and issues the actual command)

Can anyone make a tut how to make cec work. Would be a nice feature in ose if it in the ui

1 Like

Resolved the issue of detecting resolution by changing the config.txt file.
If my TV turned on after the equipment did not recognize the resolution.

uncomment to force a console size. By default it will be display’s size minus
overscan.
framebuffer_width=1920
framebuffer_height=1080

This is the maximum resolution of the TVs I have in my project. after that it worked.

1 Like

Hi, I’m just getting back on this - I’m still new to Docker, please could you show me how to how to use Celery in setting up the task of turning on and off the TVs.

This is my current setup:

#Install cec-client

$ apt-get install libcec3 cec-utils

#Install cron

$sudo apt-get update

$sudo apt-get install cron

Cron Script

#Turn off at 5:55pm

55 1 * * * echo ‘standby 0’ | cec-client -s -d 1 >/dev/null 2>&1

#Off during weekdays

55 0 * * 1-5 echo ‘standby 0’ | cec-client -s -d 1 >/dev/null 2>&1

#on during weekdays

55 13 * * 1-5 echo ‘on 0’ | cec-client -s -d 1 >/dev/null 2>&1

Also, how would one go about adding the feature to the UI to set when the screens are trigger on and Off.

Thanks!

I’m not going to lie. Porting this to Celery isn’t super straightforward. However, it would include the following steps:

  • Making sure cec-client is installed in the Celery container.
  • Creating a Periodic task in Celery that matches the schedule above.
1 Like

Okay. Will take a stab at that. So everything would be done within the Celery Container? Do I need to use Redis for the messaging? Going through the steps here - https://docs.celeryproject.org/en/stable/getting-started/first-steps-with-celery.html#first-steps

Do I need to setup a broker?

Yeah, everything should be done through the Celery (worker) container. Redis should already be part of the fabric, as we are already using Celery.