Difference between revisions of "Linux - Screen Control"

From Da Nerd Mage Wiki
Jump to navigation Jump to search
(Created page with "* <code>sudo apt install vbetool</code> The following script needs to run as root... * <code>sudo vi /usr/local/bin/screenremote.py</code> #!/usr/bin/env python import paho.mqtt.client as mqttClient import time import os import subprocess import socket ################################################################################################### hostname = socket.gethostname() broker_address = "skynet" port = 1883 topic = hostname + "/#" user = "...")
 
 
(21 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{{!}} class="wikitable" style="float: right; width: 322px;" border="2"
{{!}}+ Proven on:
{{!}}- < --="" debian="" -->
{{!}} style="text-align: center; width: 60px;" {{!}} [[File:Logo Debian.png{{!}}60px{{!}}link=https://www.debian.org/{{!}}center{{!}}middle{{!}}frameless]]
{{!}} style="text-align: center; width: 40px;" {{!}} 12 (bookworm)
{{!}}}
This little setup allows for remote control (via MQTT) of the screen(s) of Linux-based computers.
Specifically set up for all-in-one machines & laptops since these are a little difficult to shut off the screen without shutting down the machine itself.
== The Script ==
* <code>sudo apt install vbetool</code>
* <code>sudo apt install vbetool</code>
The following script needs to run as root...
The following script needs to run as root...


* <code>sudo vi /usr/local/bin/screenremote.py</code>
* <code>sudo vi /usr/local/bin/screenremote.py</code>  
 
<syntaxhighlight lang="python" line>
#!/usr/bin/env python
#!/usr/bin/env python
 
import paho.mqtt.client as mqttClient
import paho.mqtt.client as mqttClient
import time
import time
import os
import os
import subprocess
import subprocess
import socket
import socket
 
###################################################################################################
###################################################################################################
 
hostname = socket.gethostname()
hostname = socket.gethostname()
broker_address = "skynet"
broker_address = "skynet"
port = 1883
port = 1883
topic = hostname + "/#"
topic = hostname + "/#"
user = "user"
user = "user"
password = "password"
password = "password"
client = mqttClient.Client(hostname + "control")
client = mqttClient.Client(hostname + "control")
client.username_pw_set(user, password=password)
client.username_pw_set(user, password=password)
 
###################################################################################################
###################################################################################################
##    Broker Connection    ##
##    Broker Connection    ##
###################################################################################################
###################################################################################################
 
Connected = False
Connected = False
 
def on_connect(client, userdata, flags, rc):
def on_connect(client, userdata, flags, rc):
    global Connected
    global Connected
    if rc == 0:
    if rc == 0:
        print("          HostName: ", hostname)
        print("          HostName: ", hostname)
        print("Connected to broker: ", broker_address)
        print("Connected to broker: ", broker_address)
        print("      Subscribed to: ", topic)
        print("      Subscribed to: ", topic)
        print()
        print()
        Connected =True
        Connected =True
    else:
    else:
        print("Connection failed")
        print("Connection failed")
        Connected =False
        Connected =False
 
###################################################################################################
###################################################################################################
##    Message Handling    ##
##    Message Handling    ##
###################################################################################################
###################################################################################################
 
def on_message(client, userdata, message):
def on_message(client, userdata, message):
    print( " Received message: " + str(message.payload.decode("utf-8")))
    print( " Received message: " + str(message.payload.decode("utf-8")))
    print( "        on topic: " + message.topic)
    print( "        on topic: " + message.topic)
    #print( "        with QoS: " + str(message.qos))
    #print( "        with QoS: " + str(message.qos))
 
    time.sleep(1)
    time.sleep(1)
 
### Display control (turn the screen on or off...)
### Display control (turn the screen on or off...)
    if message.topic == hostname + "/display":
    if message.topic == hostname + "/display":
        command = "/usr/sbin/vbetool dpms " + str(message.payload.decode("utf-8"))
        command = "/usr/sbin/vbetool dpms " + str(message.payload.decode("utf-8"))
        print( command )
        print( command )
        os.system(command)
        os.system(command)
### Audio control (something for th future...)
### Audio control (something for th future...)
    elif message.topic == hostname + "/audio":
    elif message.topic == hostname + "/audio":
        print("audio stuff")
        print("audio stuff")
### Not any sort of valid topic...
### Not any sort of valid topic...
    else:
    else:
        print("Not Important to us...")
        print("Not Important to us...")
 
    print()
    print()
 
###################################################################################################
###################################################################################################
 
client.on_connect = on_connect
client.on_connect = on_connect
client.on_message = on_message
client.on_message = on_message
 
client.connect(broker_address, port=port)
client.connect(broker_address, port=port)
client.loop_start()
client.loop_start()
 
while Connected != True:
while Connected != True:
    time.sleep(0.1)
    time.sleep(0.1)
 
client.subscribe(topic)
client.subscribe(topic)
 
try:
try:
    while True:
    while True:
        time.sleep(1)
        time.sleep(1)
 
except KeyboardInterrupt:
except KeyboardInterrupt:
    print( "exiting" )
    print( "exiting" )
    client.disconnect()
    client.disconnect()
    client.loop_stop()
    client.loop_stop()
 
 
</syntaxhighlight>
 
* <code>sudo chmod +x /usr/local/bin/screenremote.py</code>
* <code>sudo chmod +x /usr/local/bin/screenremote.py</code>
This will respond to MQTT messages:
This will respond to MQTT messages:
Line 92: Line 109:
* '''HOSTNAME'''/display on
* '''HOSTNAME'''/display on
* '''HOSTNAME'''/display off
* '''HOSTNAME'''/display off
& works as a '''systemd''' service
 
== The Service ==
It works as a '''systemd''' service


* <code>sudo vi /etc/systemd/system/remote-screen-control.service</code>
* <code>sudo vi /etc/systemd/system/remote-screen-control.service</code>
[Unit]
 
Description=Watch for MQTT messages to turn screen on/off
<syntaxhighlight lang="ini" line>
After=multi-user.target
[Unit]
Description=Watch for MQTT messages to turn screen on/off
[Service]
Documentation=https://wiki.nerdmage.ca/index.php/Linux_-_Screen_Control
ExecStart=<code>/usr/local/bin/screenremote.py</code>
After=multi-user.target network.target
Type=simple
 
[Service]
[Install]
ExecStart=<code>/usr/local/bin/screenremote.py</code>
WantedBy=multi-user.target
Type=simple
Restart=on-failure
 
[Install]
WantedBy=multi-user.target
</syntaxhighlight>
 
* <code>sudo systemctl daemon-reload</code>
 
 
* <code>sudo systemctl enable remote-screen-control.service</code>
* <code>sudo systemctl enable remote-screen-control.service</code>
* <code>sudo systemctl start remote-screen-control.service</code>
* <code>sudo systemctl start remote-screen-control.service</code>
* <code>sudo systemctl status remote-screen-control.service</code>
* <code>sudo systemctl status remote-screen-control.service</code>
== Notes ==
=== non vbetool capable systems ===
For some systems, '''vbetool''' fails.
In this case, if the system has '''X''' installed (i.e.: it has a GUI), '''xset''' might do the job in its place.
* <code>xset -display :0.0 dpms force off</code>
* <code>xset -display :0.0 dpms force on</code>
<span style="color: rgb(186, 55, 42);" >As of yet... No solution for systems without '''X'''.</span>
=== Python Weirdness ===
Sometimes, '''Python''' & it's tools & modules are a little problematic.
Installing '''Python3''' & '''paho-mqtt''' directly will force this to work. (&, of course, you should force it to be '''Python3'''...)
* <code>sudo apt install python-is-python3 python3-paho-mqtt</code>

Latest revision as of 12:41, 26 June 2024

Proven on:
Logo Debian.png
12 (bookworm)

This little setup allows for remote control (via MQTT) of the screen(s) of Linux-based computers.

Specifically set up for all-in-one machines & laptops since these are a little difficult to shut off the screen without shutting down the machine itself.

The Script

  • sudo apt install vbetool

The following script needs to run as root...

  • sudo vi /usr/local/bin/screenremote.py
#!/usr/bin/env python

import paho.mqtt.client as mqttClient
import time
import os
import subprocess
import socket

###################################################################################################

hostname = socket.gethostname()
broker_address = "skynet"
port = 1883
topic = hostname + "/#"
user = "user"
password = "password"
client = mqttClient.Client(hostname + "control")
client.username_pw_set(user, password=password)

###################################################################################################
##    Broker Connection    ##
###################################################################################################

Connected = False

def on_connect(client, userdata, flags, rc):
    global Connected
    if rc == 0:
        print("           HostName: ", hostname)
        print("Connected to broker: ", broker_address)
        print("      Subscribed to: ", topic)
        print()
        Connected =True
    else:
        print("Connection failed")
        Connected =False

###################################################################################################
##    Message Handling    ##
###################################################################################################

def on_message(client, userdata, message):
    print( " Received message: " + str(message.payload.decode("utf-8")))
    print( "         on topic: " + message.topic)
    #print( "         with QoS: " + str(message.qos))

    time.sleep(1)

### Display control (turn the screen on or off...)
    if message.topic == hostname + "/display":
        command = "/usr/sbin/vbetool dpms " + str(message.payload.decode("utf-8"))
        print( command )
        os.system(command)
### Audio control (something for th future...)
    elif message.topic == hostname + "/audio":
        print("audio stuff")
### Not any sort of valid topic...
    else:
        print("Not Important to us...")

    print()

###################################################################################################

client.on_connect = on_connect
client.on_message = on_message

client.connect(broker_address, port=port)
client.loop_start()

while Connected != True:
    time.sleep(0.1)

client.subscribe(topic)

try:
    while True:
        time.sleep(1)

except KeyboardInterrupt:
    print( "exiting" )
    client.disconnect()
    client.loop_stop()
  • sudo chmod +x /usr/local/bin/screenremote.py

This will respond to MQTT messages:

  • HOSTNAME/display on
  • HOSTNAME/display off

The Service

It works as a systemd service

  • sudo vi /etc/systemd/system/remote-screen-control.service
[Unit]
Description=Watch for MQTT messages to turn screen on/off
Documentation=https://wiki.nerdmage.ca/index.php/Linux_-_Screen_Control
After=multi-user.target network.target

[Service]
ExecStart=<code>/usr/local/bin/screenremote.py</code>
Type=simple
Restart=on-failure

[Install]
WantedBy=multi-user.target
  • sudo systemctl daemon-reload


  • sudo systemctl enable remote-screen-control.service
  • sudo systemctl start remote-screen-control.service
  • sudo systemctl status remote-screen-control.service

Notes

non vbetool capable systems

For some systems, vbetool fails.

In this case, if the system has X installed (i.e.: it has a GUI), xset might do the job in its place.

  • xset -display :0.0 dpms force off
  • xset -display :0.0 dpms force on

As of yet... No solution for systems without X.

Python Weirdness

Sometimes, Python & it's tools & modules are a little problematic.

Installing Python3 & paho-mqtt directly will force this to work. (&, of course, you should force it to be Python3...)

  • sudo apt install python-is-python3 python3-paho-mqtt