2021-11-16: To optimize automatic backups, thumbnails are now created during the secondary backup (to cloud storage) instead of between the primary (to local disk) and secondary backups. This approach maximizes computing and network efficiency, significantly reducing the overall backup time.
2021-10-19: Add option to rename media files after backup based on the files creation date and time. Example: "Image.jpg" from 2024/10/19 12:42:14 will be renamed to "2024-10-19_12-42-14_-_Image.jpg"
2024-09-09: In the settings for both default backups, specify separately whether the files should be copied or moved; Allow moving files from former target devices; bugfixes
diff --git a/scripts/display.py b/scripts/display.py
index c3eed47..334fcba 100644
--- a/scripts/display.py
+++ b/scripts/display.py
@@ -30,6 +30,7 @@
# s=b: BASIC
# s=h: HIGHLIGHT
# s=a: ALERT
+# s=s: statusbar
#
## u: underline
#
@@ -50,7 +51,9 @@
# kill: terminate display daemen
import os
+import RPi.GPIO
import shutil
+import subprocess
import sys
import threading
import time
@@ -68,14 +71,17 @@
import displaymenu
from lib_display import display_content_files
-#import lib_debug
-#xx = lib_debug.debug()
+# import lib_debug
+# xx = lib_debug.debug()
WORKING_DIR = os.path.dirname(__file__)
class DISPLAY(object):
def __init__(self):
+ # cleanup pins
+ RPi.GPIO.cleanup()
+
# objects
self.__setup = lib_setup.setup()
self.__display_content_files = display_content_files(self.__setup)
@@ -98,6 +104,7 @@ def __init__(self):
self.conf_DISP_FONT_SIZE = self.__setup.get_val('conf_DISP_FONT_SIZE')
self.conf_DISP_BLACK_ON_POWER_OFF = self.__setup.get_val('conf_DISP_BLACK_ON_POWER_OFF')
self.conf_DISP_FRAME_TIME = self.__setup.get_val('conf_DISP_FRAME_TIME')
+ self.conf_DISP_SHOW_STATUSBAR = self.__setup.get_val('conf_DISP_SHOW_STATUSBAR')
self.conf_MENU_ENABLED = self.__setup.get_val('conf_MENU_ENABLED')
self.const_DISPLAY_CONTENT_OLD_FILE = self.__setup.get_val('const_DISPLAY_CONTENT_OLD_FILE')
@@ -208,11 +215,53 @@ def calculate_LineSize(self):
self.line_height = bottom - top
self.maxLines = int(self.device.height / self.line_height)
+
if self.maxLines > self.const_DISPLAY_LINES_LIMIT:
self.maxLines = self.const_DISPLAY_LINES_LIMIT
else:
self.maxLines = self.const_DISPLAY_LINES_LIMIT
+ def get_status_bar(self):
+ status_bar = []
+
+ #comitup
+ try:
+ comitup_status = subprocess.check_output(['comitup-cli', 'i']).decode().split('\n')
+ except:
+ comitup_status = []
+
+ for status in comitup_status:
+ if status.endswith(' state'):
+
+ if status.startswith('HOTSPOT'):
+ status_bar += ['HOT']
+ elif status.startswith('CONNECTING'):
+ status_bar += ['..?']
+ elif status.startswith('CONNECTED'):
+ status_bar += ['WiFi']
+ break
+
+ # CPU usage
+ try:
+ vmstat = subprocess.check_output(['vmstat']).decode().strip().split('\n')
+ except:
+ vmstat = []
+
+ if vmstat:
+ vmstat_fields = vmstat[-1].split()
+
+ if len(vmstat_fields) >= 14:
+ status_bar += [f'{100-float(vmstat_fields[14]):.0f}%']
+
+ # temperature
+ try:
+ temp_c = float(subprocess.check_output(['sudo', 'cat', '/sys/class/thermal/thermal_zone0/temp']).decode()) / 1000
+ status_bar += [f'{temp_c:.0f}°C']
+ except:
+ pass
+
+ return(status_bar)
+
def show(self, Lines):
if ":IMAGE=" in Lines[0]:
@@ -234,6 +283,10 @@ def show(self, Lines):
else:
# Write lines
+
+ if self.conf_DISP_SHOW_STATUSBAR:
+ Lines[self.maxLines-1] = f's=s:STATUSBAR'
+
with canvas(self.device) as draw:
# define constants
@@ -272,8 +325,11 @@ def show(self, Lines):
if FormatValue == 'h': # highlight
fg_fill = self.color_bg
bg_fill = self.color_text
- if FormatValue == 'a': # alert
+ elif FormatValue == 'a': # alert
underline = True
+ elif FormatValue == 's': # statusbar
+ fg_fill = self.color_bg
+ bg_fill = self.color_text
else:
# RGB(A)
if FormatValue == 'h' or FormatValue == 'hc': # highlight or highlight color
@@ -286,6 +342,9 @@ def show(self, Lines):
bg_fill = self.color_high
else:
underline = True
+ elif FormatValue == 's': # statusbar
+ fg_fill = self.color_bg
+ bg_fill = self.color_text
if FormatType == 'u':
underline = True
@@ -294,7 +353,7 @@ def show(self, Lines):
# Draw a filled box in case of inverted output
if bg_fill != self.color_bg:
- draw.rectangle((x, y, self.device.width, y + self.line_height), outline=bg_fill, fill=bg_fill)
+ draw.rectangle((x, y + 2, self.device.width, y + self.line_height + 1 if y + self.line_height + 1 <= self.device.height else self.device.height ), outline=bg_fill, fill=bg_fill)
if Content[0:6] == "IMAGE=":
Content = ''
@@ -338,7 +397,28 @@ def show(self, Lines):
draw.rectangle((pgbar_x_l, pgbar_y_u, pgbar_x_r, pgbar_y_d), outline=bg_fill, fill=fg_fill)
# Write text
- draw.text((x + 1, y), Content, font=self.FONT, fill=fg_fill)
+ ## status bar
+ if FormatType == 's' and FormatValue == 's':
+ status_bar = self.get_status_bar()
+
+ i = 0
+ for item in status_bar:
+
+ if i < len(status_bar) - 1:
+ # align left
+ x = int(i * self.device.width / len(status_bar))
+ else:
+ # align right
+ (left, top, right, bottom) = draw.textbbox((0,0), item,font=self.FONT)
+ pgbar_text_length = right - left
+ x = self.device.width - pgbar_text_length - 1
+
+ draw.text((x + 1, y), item, font=self.FONT, fill=fg_fill)
+
+ i += 1
+ else:
+ ## regular text
+ draw.text((x + 1, y), Content, font=self.FONT, fill=fg_fill)
if underline:
(left, top, right, bottom) = draw.textbbox((0,0),Content,font=self.FONT)
diff --git a/scripts/lang/de.json b/scripts/lang/de.json
index f929376..9f652ea 100644
--- a/scripts/lang/de.json
+++ b/scripts/lang/de.json
@@ -278,7 +278,7 @@
"connection_label": "Welche Schnittstelle soll verwendet werden?",
"i2c_address_label": "i2c-Adresse des Displays",
"i2c_header": "I2C-Display-Konfiguration",
- "ip_label": "Wenn die Anzeige aktiviert ist, IP minütlich einblenden.",
+ "ip_label": "IP minütlich einblenden.",
"black_on_power_off_label": "Display beim Herunterfahren ausschalten",
"device_available": "Gerät erkannt",
"behavior_header": "Display-Verhalten",
@@ -313,7 +313,10 @@
"rotate_header": "Display drehen",
"offset_x_label": "Display-Verschiebung horizontal (in Pixeln)",
"offset_y_label": "Display-Verschiebung vertikal (in Pixeln)",
- "frame_time_ip_label": "Minimale Anzeigedauer der IP in Sekunden"
+ "frame_time_ip_label": "Minimale Anzeigedauer der IP in Sekunden",
+ "statusbar": {
+ "label": "Statusleiste einblenden"
+ }
},
"menu": {
"section": "Display-Menü",
diff --git a/scripts/lang/en.json b/scripts/lang/en.json
index 3eac911..c9137be 100644
--- a/scripts/lang/en.json
+++ b/scripts/lang/en.json
@@ -508,7 +508,7 @@
"connection_label": "Which interface should be used?",
"i2c_address_label": "i2c address of the display",
"i2c_header": "I2C display configuration",
- "ip_label": "If display is activated, print IP every minute.",
+ "ip_label": "Print IP every minute.",
"black_on_power_off_label": "Display off when shutting down",
"device_available": "Device detected",
"behavior_header": "Display behavior",
@@ -543,7 +543,10 @@
"rotate_header": "Rotate screen",
"offset_x_label": "Display shift horizontally (in pixels)",
"offset_y_label": "Display shift vertically (in pixels)",
- "frame_time_ip_label": "Minimum display time of the IP in seconds"
+ "frame_time_ip_label": "Minimum display time of the IP in seconds",
+ "statusbar": {
+ "label": "Show status bar"
+ }
},
"menu": {
"section": "Display menu",
diff --git a/scripts/lang/es.json b/scripts/lang/es.json
index cad6d7d..348d1ae 100644
--- a/scripts/lang/es.json
+++ b/scripts/lang/es.json
@@ -278,7 +278,7 @@
"connection_label": "¿Qué interfaz se debe utilizar?",
"i2c_address_label": "Dirección i2c de la pantalla",
"i2c_header": "Configuración de pantalla I2C",
- "ip_label": "Si la pantalla está activada, imprimir IP cada minuto.",
+ "ip_label": "Imprimir IP cada minuto.",
"black_on_power_off_label": "Apague la pantalla al apagar",
"device_available": "Dispositivo detectado",
"behavior_header": "Comportamiento de visualización",
@@ -313,7 +313,10 @@
"rotate_header": "Girar pantalla",
"offset_x_label": "Desplazamiento de la pantalla horizontalmente (en píxeles)",
"offset_y_label": "Desplazamiento de la pantalla verticalmente (en píxeles)",
- "frame_time_ip_label": "Tiempo mínimo de visualización de la IP en segundos"
+ "frame_time_ip_label": "Tiempo mínimo de visualización de la IP en segundos",
+ "statusbar": {
+ "label": "Mostrar barra de estado"
+ }
},
"menu": {
"section": "Mostrar menú",
diff --git a/scripts/lang/fr.json b/scripts/lang/fr.json
index 38e8418..b489abf 100644
--- a/scripts/lang/fr.json
+++ b/scripts/lang/fr.json
@@ -278,7 +278,7 @@
"connection_label": "Quelle interface utiliser ?",
"i2c_address_label": "Adresse i2c de l'écran",
"i2c_header": "Configuration de l'affichage I2C",
- "ip_label": "Si l'affichage est activé, imprimez l'IP toutes les minutes.",
+ "ip_label": "Imprimez l'IP toutes les minutes.",
"black_on_power_off_label": "Éteignez l'écran lors de l'arrêt",
"device_available": "Périphérique détecté",
"behavior_header": "Comportement d'affichage",
@@ -313,7 +313,10 @@
"rotate_header": "Rotation de l'écran",
"offset_x_label": "Décalage d'affichage horizontal (en pixels)",
"offset_y_label": "Décalage d'affichage vertical (en pixels)",
- "frame_time_ip_label": "Temps d'affichage minimum de l'IP en secondes"
+ "frame_time_ip_label": "Temps d'affichage minimum de l'IP en secondes",
+ "statusbar": {
+ "label": "Afficher la barre d'état"
+ }
},
"menu": {
"section": "Afficher le menu",
diff --git a/scripts/lib_setup.py b/scripts/lib_setup.py
index 7f9d1dc..76b1b5c 100644
--- a/scripts/lib_setup.py
+++ b/scripts/lib_setup.py
@@ -240,6 +240,7 @@ def __get_config_standard(self):
'conf_DISP_FRAME_TIME_IP': {'value': 2.0, 'type': 'float'},
'conf_DISP_BLACK_ON_POWER_OFF': {'value': True, 'type': 'bool'},
'conf_DISP_IP_REPEAT': {'value': True, 'type': 'bool'},
+ 'conf_DISP_SHOW_STATUSBAR': {'value': True, 'type': 'bool'},
'conf_MENU_ENABLED': {'value': True, 'type': 'bool'},
'conf_MENU_BUTTON_COMBINATION': {'value': '1', 'type': 'str'},
'conf_MENU_BUTTON_ROTATE': {'value': 2, 'type': 'int'},
diff --git a/scripts/setup.php b/scripts/setup.php
index b159325..df13d0b 100644
--- a/scripts/setup.php
+++ b/scripts/setup.php
@@ -194,6 +194,7 @@ function write_config() {
$conf_DISP = isset($conf_DISP)?'true':'false';
$conf_DISP_BLACK_ON_POWER_OFF = isset($conf_DISP_BLACK_ON_POWER_OFF)?'true':'false';
$conf_DISP_IP_REPEAT = isset($conf_DISP_IP_REPEAT)?'true':'false';
+ $conf_DISP_SHOW_STATUSBAR = isset($conf_DISP_SHOW_STATUSBAR)?'true':'false';
$conf_MENU_ENABLED = isset($conf_MENU_ENABLED)?'true':'false';
$conf_VIRTUAL_KEYBOARD_ENABLED = isset($conf_VIRTUAL_KEYBOARD_ENABLED)?'true':'false';
$conf_LOG_SYNC = isset($conf_LOG_SYNC)?'true':'false';
@@ -281,6 +282,7 @@ function write_config() {
conf_DISP_FRAME_TIME_IP=$conf_DISP_FRAME_TIME_IP
conf_DISP_BLACK_ON_POWER_OFF=$conf_DISP_BLACK_ON_POWER_OFF
conf_DISP_IP_REPEAT=$conf_DISP_IP_REPEAT
+conf_DISP_SHOW_STATUSBAR=$conf_DISP_SHOW_STATUSBAR
conf_MENU_ENABLED=$conf_MENU_ENABLED
conf_MENU_BUTTON_COMBINATION='$conf_MENU_BUTTON_COMBINATION'
conf_MENU_BUTTON_ROTATE='$conf_MENU_BUTTON_ROTATE'
@@ -818,6 +820,9 @@ function upload_settings() {
>