[IMP] iot: Dual screen support for RPI4

We now support the RPI4 which has 2 micro-HDMI outputs, while the
prvious driver only supported one display. We add support for a second
display.

Taskid: 2123511
X-original-commit: 5886c3a864c990fcd7b852baafab752e7da90494
This commit is contained in:
Antoine Prieels
2019-11-27 14:15:18 +00:00
parent c1c4404131
commit ad846fcee5
6 changed files with 97 additions and 19 deletions
+13 -7
View File
@@ -6,7 +6,7 @@ from usb import core
from gatt import DeviceManager as Gatt_DeviceManager
import subprocess
import json
from re import sub
from re import sub, finditer
import urllib3
import os
import socket
@@ -302,14 +302,20 @@ class Manager(Thread):
def get_connected_displays(self):
display_devices = {}
hdmi = subprocess.check_output(['tvservice', '-n']).decode('utf-8').replace('\n', '')
if hdmi.find('=') != -1 and hdmi.split('=')[1] != "Unk-Composite dis":
hdmi_serial = sub('[^a-zA-Z0-9 ]+', '', hdmi.split('=')[1]).replace(' ', '_')
displays = subprocess.check_output(['tvservice', '-l']).decode()
x_screen = 0
for match in finditer('Display Number (\d), type HDMI (\d)', displays):
display_id, hdmi_id = match.groups()
display_name = subprocess.check_output(['tvservice', '-nv', display_id]).decode().rstrip().split('=')[1]
display_identifier = sub('[^a-zA-Z0-9 ]+', '', display_name).replace(' ', '_') + "_" + str(hdmi_id)
iot_device = IoTDevice({
'identifier': hdmi_serial,
'name': hdmi.split('=')[1],
'identifier': display_identifier,
'name': display_name,
'x_screen': str(x_screen),
}, 'display')
display_devices[hdmi_serial] = iot_device
display_devices[display_identifier] = iot_device
x_screen += 1
if not len(display_devices):
# No display connected, create "fake" device to be accessed from another computer
+13 -10
View File
@@ -35,8 +35,9 @@ class DisplayDriver(Driver):
self.event_data = threading.Event()
self.owner = False
self.rendered_html = ''
self.load_url()
self.call_xdotools('F11')
if self.device_identifier != 'distant_display':
self._x_screen = device.get('x_screen', '0')
self.load_url()
@property
def device_identifier(self):
@@ -68,20 +69,22 @@ class DisplayDriver(Driver):
event_manager.device_changed(self)
def run(self):
while True:
while self.device_identifier != 'distant_display':
time.sleep(60)
if self.url != 'http://localhost:8069/point_of_sale/display/':
# Refresh the page every minute
self.call_xdotools('F5')
def update_url(self, url=None):
os.environ['DISPLAY'] = ":0." + self._x_screen
os.environ['XAUTHORITY'] = '/run/lightdm/pi/xauthority'
firefox_env = os.environ.copy()
firefox_env['HOME'] = '/tmp'
firefox_env['DISPLAY'] = ':0.0'
firefox_env['XAUTHORITY'] = '/run/lightdm/pi/xauthority'
firefox_env['HOME'] = '/tmp/' + self._x_screen
self.url = url or 'http://localhost:8069/point_of_sale/display/'
if self.device_identifier != 'distant_display':
subprocess.Popen(['firefox', self.url], env=firefox_env)
new_window = subprocess.call(['xdotool', 'search', '--onlyvisible', '--screen', self._x_screen, '--class', 'Firefox'])
subprocess.Popen(['firefox', self.url], env=firefox_env)
if new_window:
self.call_xdotools('F11')
def load_url(self):
url = None
@@ -101,10 +104,10 @@ class DisplayDriver(Driver):
return self.update_url(url)
def call_xdotools(self, keystroke):
os.environ['DISPLAY'] = ":0.0"
os.environ['DISPLAY'] = ":0." + self._x_screen
os.environ['XAUTHORITY'] = "/run/lightdm/pi/xauthority"
try:
subprocess.call(['xdotool', 'search', '--sync', '--onlyvisible', '--class', 'Firefox', 'windowactivate', 'key', keystroke])
subprocess.call(['xdotool', 'search', '--sync', '--onlyvisible', '--screen', self._x_screen, '--class', 'Firefox', 'key', keystroke])
return "xdotool succeeded in stroking " + keystroke
except:
return "xdotool threw an error, maybe it is not installed on the IoTBox"
@@ -0,0 +1,60 @@
Section "Device"
Identifier "fbdev0"
Driver "fbdev"
Option "fbdev" "/dev/fb0"
EndSection
Section "Device"
Identifier "fbdev1"
Driver "fbdev"
Option "fbdev" "/dev/fb1"
EndSection
# Dummy device to use Xlib in KeyboardUSBDriver when no monitor is connected
Section "Device"
Identifier "dummy"
Driver "dummy"
EndSection
Section "Monitor"
Identifier "Monitor0"
EndSection
Section "Monitor"
Identifier "Monitor1"
EndSection
Section "Monitor"
Identifier "DummyMonitor"
EndSection
Section "Screen"
Identifier "Screen0"
Monitor "Monitor0"
Device "fbdev0"
Subsection "Display"
EndSubSection
EndSection
Section "Screen"
Identifier "Screen1"
Monitor "Monitor1"
Device "fbdev1"
Subsection "Display"
EndSubSection
EndSection
Section "Screen"
Identifier "DummyScreen"
Monitor "DummyMonitor"
Device "dummy"
Subsection "Display"
EndSubSection
EndSection
Section "ServerLayout"
Identifier "Multihead"
Screen 0 "Screen0"
Screen 1 "Screen1" rightof "Screen0"
Screen 2 "DummyScreen" rightof "Screen1"
EndSection
@@ -3,6 +3,6 @@
user-authority-in-system-dir=true
[SeatDefaults]
xserver-command=/usr/bin/X -s 0 dpms -nolisten tcp
xserver-command=/usr/bin/X -s 0 -layout Multihead dpms -nolisten tcp
greeter-hide-users=false
autologin-user=pi
autologin-user=pi
@@ -50,6 +50,7 @@ PKGS_TO_INSTALL="
xdotool \
unclutter \
x11-utils \
xserver-xorg-video-dummy \
openbox \
rpi-update \
adduser \
@@ -159,6 +160,9 @@ systemctl disable hostapd.service
# cf: https://www.raspberrypi.org/documentation/configuration/raspi-config.md
echo "disable_overscan=1" >> /boot/config.txt
# Separate framebuffers for both screens on RPI4
sed -i '/dtoverlay/d' /boot/config.txt
# exclude /drivers folder from git info to be able to load specific drivers
echo "addons/hw_drivers/drivers/" > /home/pi/odoo/.git/info/exclude
@@ -0,0 +1,5 @@
# Start Openbox on the second display as described in
# http://openbox.org/wiki/Help:FAQ > "How do I run Openbox across multiple X screens?"
XAUTHORITY=/run/lightdm/pi/xauthority DISPLAY=:0.1 openbox &
exec openbox-session