From a9fd91f47cd843120a1ee6216db836ba9eaf2501 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sat, 20 Jun 2026 18:20:40 +0200
Subject: [PATCH 01/10] Add configurable log filters for daemon logs
Introduce a log filters feature to allow pattern-based remapping or dropping of daemon log records.
- UI: add a modal (desktop/modal/logfilters.tvremote.php) and JS (desktop/js/logfilters.tvremote.js) to manage filters (enable/disable, pattern, target level). Add a button and checkbox in plugin configuration to open the manager and enable filters.
- Backend PHP: add AJAX handler (saveLogFilters) in core/ajax/tvremote.ajax.php and file helpers in core/class/tvremote.class.php (create/get/save logfilters.json). Install/update now initializes config key and ensures the filters file exists.
- Daemon/Python: extend config to include log filters settings and file path (resources/tvremoted/config.py), add a PatternRemapFilter to remap/drop log records and wire it into logging when enabled (resources/tvremoted/tvremoted.py). Add command-line arg propagation from PHP when starting the daemon.
- Other: bump pluginVersion to 1.4.0, add data/filters/README.md and ignore data/filters/*.json in .gitignore, update .vscode/settings.json.
Notes: logfilters.json is stored in data/filters/ and is gitignored; enabling filters requires restarting the daemon.
---
.gitignore | 3 +
.vscode/settings.json | 1 +
core/ajax/tvremote.ajax.php | 10 ++
core/class/tvremote.class.php | 23 ++++
data/filters/README.md | 1 +
desktop/js/logfilters.tvremote.js | 146 ++++++++++++++++++++++++++
desktop/modal/logfilters.tvremote.php | 44 ++++++++
plugin_info/configuration.php | 26 +++++
plugin_info/info.json | 2 +-
plugin_info/install.php | 10 ++
resources/tvremoted/config.py | 8 ++
resources/tvremoted/tvremoted.py | 53 ++++++++++
12 files changed, 326 insertions(+), 1 deletion(-)
create mode 100644 data/filters/README.md
create mode 100644 desktop/js/logfilters.tvremote.js
create mode 100644 desktop/modal/logfilters.tvremote.php
diff --git a/.gitignore b/.gitignore
index 64a574d..90e00b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+# Plugin Configuration
+data/filters/*.json
+
# IDE & Editors
.vscode/*
!.vscode/settings.json
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 600a248..1b576a9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -50,6 +50,7 @@
"lastscan",
"lasttime",
"lastused",
+ "logfilters",
"maxrss",
"molotov",
"mycanal",
diff --git a/core/ajax/tvremote.ajax.php b/core/ajax/tvremote.ajax.php
index 8d2200b..5cad1f6 100644
--- a/core/ajax/tvremote.ajax.php
+++ b/core/ajax/tvremote.ajax.php
@@ -65,6 +65,16 @@
ajax::success(tvremote::sendBeginPairingAdb(init('mac'), init('host')));
}
+ if (init('action') == 'saveLogFilters') {
+ $data = init('logFiltersData');
+ $filters = json_decode(is_string($data) ? $data : '[]', true);
+ if (!is_array($filters)) {
+ ajax::error(__('Format de données invalide', __FILE__));
+ }
+ tvremote::saveLogFilters($filters);
+ ajax::success();
+ }
+
throw new Exception(__('Aucune méthode correspondante à', __FILE__) . ' : ' . init('action'));
/* * *********Catch exception*************** */
} catch (Exception $e) {
diff --git a/core/class/tvremote.class.php b/core/class/tvremote.class.php
index d9b0298..18be928 100644
--- a/core/class/tvremote.class.php
+++ b/core/class/tvremote.class.php
@@ -138,6 +138,7 @@ public static function deamon_start() {
$cmd = self::PYTHON3_PATH . " {$path}/tvremoted.py";
$cmd .= ' --loglevel ' . log::convertLogLevel(log::getLogLevel(__CLASS__));
$cmd .= ' --tvloglevel ' . config::byKey('tvLogLevel', __CLASS__, 'daemon');
+ $cmd .= ' --logfiltersenabled ' . (config::byKey('logFiltersEnabled', __CLASS__, '0') ? '1' : '0');
$cmd .= ' --pluginversion ' . config::byKey('pluginVersion', __CLASS__, '0.0.0');
$cmd .= ' --socketport ' . config::byKey('socketport', __CLASS__, '55112');
$cmd .= ' --cyclefactor ' . config::byKey('cyclefactor', __CLASS__, '1.0');
@@ -559,6 +560,28 @@ public function disableADBToDaemon() {
}
}
+ public static function createLogFiltersFile() {
+ $path = dirname(__FILE__) . '/../../data/filters/logfilters.json';
+ if (!file_exists($path)) {
+ file_put_contents($path, '[]');
+ }
+ }
+
+ public static function getLogFiltersFileContent() {
+ $path = dirname(__FILE__) . '/../../data/filters/logfilters.json';
+ if (!file_exists($path)) {
+ return array();
+ }
+ return json_decode(file_get_contents($path), true) ?: array();
+ }
+
+ public static function saveLogFilters($filters) {
+ $path = dirname(__FILE__) . '/../../data/filters/logfilters.json';
+ if (file_put_contents($path, json_encode($filters, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)) === false) {
+ throw new Exception(__('Impossible d\'enregistrer le fichier logfilters.json', __FILE__));
+ }
+ }
+
public static function pairingException($_data) {
if (!isset($_data['pairing_mac'])) {
log::add('tvremote', 'error', '[PAIRING][EXCEPTION] Information manquante (MAC) pour mettre à jour l\'équipement');
diff --git a/data/filters/README.md b/data/filters/README.md
new file mode 100644
index 0000000..f31918e
--- /dev/null
+++ b/data/filters/README.md
@@ -0,0 +1 @@
+Log filters are stored here as `logfilters.json` (gitignored).
diff --git a/desktop/js/logfilters.tvremote.js b/desktop/js/logfilters.tvremote.js
new file mode 100644
index 0000000..5d3df35
--- /dev/null
+++ b/desktop/js/logfilters.tvremote.js
@@ -0,0 +1,146 @@
+/* This file is part of Jeedom.
+ *
+ * Jeedom is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Jeedom is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jeedom. If not, see .
+ */
+
+(() => {
+'use strict'
+
+const AJAX_URL = 'plugins/tvremote/core/ajax/tvremote.ajax.php'
+const LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'DROP']
+
+function buildLevelSelect(selected) {
+ const select = document.createElement('select')
+ select.className = 'form-control lf-level'
+ LEVELS.forEach(function(l) {
+ const opt = document.createElement('option')
+ opt.value = l
+ opt.textContent = l === 'DROP' ? '---' : l
+ opt.selected = l === selected
+ select.appendChild(opt)
+ })
+ return select
+}
+
+function addRow(item) {
+ item = item || {}
+ const container = document.getElementById('logFiltersContainer')
+ if (!container) return
+ const enabled = item.enabled !== false
+ const level = ((item.level || 'DEBUG') + '').toUpperCase()
+
+ const row = document.createElement('tr')
+ row.className = 'logFilterItem'
+
+ const tdCheck = document.createElement('td')
+ tdCheck.style.textAlign = 'center'
+ const cb = document.createElement('input')
+ cb.type = 'checkbox'
+ cb.className = 'lf-enabled'
+ cb.checked = enabled
+ tdCheck.appendChild(cb)
+
+ const tdPattern = document.createElement('td')
+ const input = document.createElement('input')
+ input.type = 'text'
+ input.className = 'form-control lf-pattern'
+ input.placeholder = '{{Ex: Cannot connect (device may be offline)}}'
+ input.value = item.pattern || ''
+ tdPattern.appendChild(input)
+
+ const tdLevel = document.createElement('td')
+ tdLevel.appendChild(buildLevelSelect(level))
+
+ const tdRemove = document.createElement('td')
+ tdRemove.style.textAlign = 'center'
+ const icon = document.createElement('i')
+ icon.className = 'fas fa-minus-circle lf-remove icon_red'
+ icon.style.cursor = 'pointer'
+ icon.title = '{{Supprimer}}'
+ tdRemove.appendChild(icon)
+
+ row.append(tdCheck, tdPattern, tdLevel, tdRemove)
+ container.appendChild(row)
+}
+
+function collectRows() {
+ const rows = document.querySelectorAll('.logFilterItem')
+ const result = []
+ rows.forEach(function(row) {
+ const pattern = row.querySelector('.lf-pattern').value.trim()
+ if (!pattern) return
+ result.push({
+ enabled: row.querySelector('.lf-enabled').checked,
+ pattern: pattern,
+ level: row.querySelector('.lf-level').value
+ })
+ })
+ return result
+}
+
+window.initLogFilters = function(data) {
+ const dataArray = Array.isArray(data) ? data : []
+ dataArray.forEach(addRow)
+
+ const addBtn = document.getElementById('bt_addLogFilter')
+ if (addBtn) addBtn.addEventListener('click', function() { addRow({}) })
+
+ const container = document.getElementById('logFiltersContainer')
+ if (container) {
+ container.addEventListener('click', function(e) {
+ const btn = e.target.closest('.lf-remove')
+ if (btn) btn.closest('.logFilterItem').remove()
+ })
+ }
+
+ const selectAllBtn = document.getElementById('bt_selectAllLogFilters')
+ if (selectAllBtn) selectAllBtn.addEventListener('click', function() {
+ document.querySelectorAll('.lf-enabled').forEach(function(cb) { cb.checked = true })
+ })
+
+ const unselectAllBtn = document.getElementById('bt_unselectAllLogFilters')
+ if (unselectAllBtn) unselectAllBtn.addEventListener('click', function() {
+ document.querySelectorAll('.lf-enabled').forEach(function(cb) { cb.checked = false })
+ })
+
+ document.querySelectorAll('.tvremote-logfilter-suggest').forEach(function(link) {
+ link.addEventListener('click', function(e) {
+ e.preventDefault()
+ addRow({ pattern: link.dataset.pattern, level: link.dataset.level, enabled: true })
+ })
+ })
+
+ const saveBtn = document.getElementById('bt_saveLogFilters')
+ if (saveBtn) saveBtn.addEventListener('click', function() {
+ const filters = collectRows()
+ domUtils.ajax({
+ type: 'POST',
+ url: AJAX_URL,
+ data: { action: 'saveLogFilters', logFiltersData: JSON.stringify(filters) },
+ dataType: 'json',
+ error: function(request) {
+ jeedomUtils.showAlert({ message: (request.responseJSON && request.responseJSON.result) || '{{Erreur lors de la sauvegarde}}', level: 'danger' })
+ },
+ success: function(data) {
+ if (data.state !== 'ok') {
+ jeedomUtils.showAlert({ message: data.result, level: 'danger' })
+ return
+ }
+ jeedomUtils.showAlert({ message: '{{Filtres sauvegardés}}', level: 'success' })
+ }
+ })
+ })
+}
+
+})()
diff --git a/desktop/modal/logfilters.tvremote.php b/desktop/modal/logfilters.tvremote.php
new file mode 100644
index 0000000..f20b376
--- /dev/null
+++ b/desktop/modal/logfilters.tvremote.php
@@ -0,0 +1,44 @@
+
+
+
+
+
+ {{Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez/décochez pour activer/désactiver une règle sans la perdre.}}
+
+
+ {{Sauvegarder}}
+
+
+
+
+
+
+
+
+ {{Actif}}
+ {{Pattern (sous-chaîne du message de log)}}
+ {{Niveau cible}}
+
+
+
+
+
+
+
+
+
+
diff --git a/plugin_info/configuration.php b/plugin_info/configuration.php
index 683bd55..ffb23ba 100644
--- a/plugin_info/configuration.php
+++ b/plugin_info/configuration.php
@@ -129,6 +129,20 @@
+
@@ -185,5 +199,17 @@ function setupResetButton(selector, action, successMessage) {
setupResetButton('.customclass-resettvcertkey', 'resetTVCertKey', '{{Reset TV Cert (OK)}}')
setupResetButton('.customclass-resetadbkeys', 'resetAdbKeys', '{{Reset ADB Keys (OK)}}')
+
+ // Filtres de logs
+ document.querySelector('.customclass-openlogfilters')?.addEventListener('click', function() {
+ jeeDialog.dialog({
+ id: 'md_logFiltersTvremote',
+ title: '{{Filtres de logs}}',
+ contentUrl: 'index.php?v=d&plugin=tvremote&modal=logfilters.tvremote',
+ width: '65%',
+ height: '60%',
+ top: '18vh'
+ })
+ })
})()
diff --git a/plugin_info/info.json b/plugin_info/info.json
index 8fb389a..82c34c8 100644
--- a/plugin_info/info.json
+++ b/plugin_info/info.json
@@ -1,7 +1,7 @@
{
"id": "tvremote",
"name": "TV Remote",
- "pluginVersion": "1.3.21",
+ "pluginVersion": "1.4.0",
"description": {
"fr_FR": "Plugin pour contrôler les équipements Android de type Télévision (Sony, Nvidia Shield, Freebox TV, etc...) via le service de télécommande Google (TVRemote) ou via ADB. Il permet de contrôler les différentes fonctions de sa télévision (power, volume, entrées HDMI, lancement d'applications, chaînes TV, navigation dans l'interface, etc...)",
"en_US": "Plugin to control Android TV devices (Sony, Nvidia Shield, Freebox TV, etc...) via Google remote control service (TVRemote) or via ADB. It allows you to control various functions of your TV (power, volume, HDMI inputs, launching applications, TV channels, navigating the interface, etc...)",
diff --git a/plugin_info/install.php b/plugin_info/install.php
index 2916daa..06c9ea4 100644
--- a/plugin_info/install.php
+++ b/plugin_info/install.php
@@ -55,6 +55,11 @@ function tvremote_install() {
if (config::byKey('disableUpdateMsg', 'tvremote') == '') {
config::save('disableUpdateMsg', '0', 'tvremote');
}
+ if (config::byKey('logFiltersEnabled', 'tvremote') == '') {
+ config::save('logFiltersEnabled', '0', 'tvremote');
+ }
+
+ tvremote::createLogFiltersFile();
$dependencyInfo = tvremote::dependancy_info();
if (!isset($dependencyInfo['state'])) {
@@ -108,6 +113,11 @@ function tvremote_update() {
if (config::byKey('disableUpdateMsg', 'tvremote') == '') {
config::save('disableUpdateMsg', '0', 'tvremote');
}
+ if (config::byKey('logFiltersEnabled', 'tvremote') == '') {
+ config::save('logFiltersEnabled', '0', 'tvremote');
+ }
+
+ tvremote::createLogFiltersFile();
$dependencyInfo = tvremote::dependancy_info();
if (!isset($dependencyInfo['state'])) {
diff --git a/resources/tvremoted/config.py b/resources/tvremoted/config.py
index 9b7ee9c..fed6b02 100644
--- a/resources/tvremoted/config.py
+++ b/resources/tvremoted/config.py
@@ -25,6 +25,10 @@ def __init__(self, **kwargs):
self.known_hosts = [] # Hosts for AndroidTVRemote2
self.known_hosts_adb = [] # Hosts for ADB
self.remote_mac = [] # MAC addresses for AndroidTVRemote2
+
+ self.log_filters_enabled: bool = False
+ self.log_filters: list = [] # [{ "pattern": str, "level": str, "enabled": bool }]
+ self.log_filters_file_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'data/filters/logfilters.json'))
self.remote_mac_adb = [] # MAC addresses for ADB
self.remote_names = [] # Names for AndroidTVRemote2
self.remote_names_adb = [] # Names for ADB
@@ -126,6 +130,10 @@ def log_level(self):
def tv_log_level(self):
return self._kwargs.get('tvloglevel', 'daemon')
+ @property
+ def log_filters_enabled_arg(self):
+ return self._kwargs.get('logfiltersenabled', '0')
+
@property
def api_key(self):
return self._kwargs.get('apikey', '')
diff --git a/resources/tvremoted/tvremoted.py b/resources/tvremoted/tvremoted.py
index 0334c47..085a313 100644
--- a/resources/tvremoted/tvremoted.py
+++ b/resources/tvremoted/tvremoted.py
@@ -1554,10 +1554,44 @@ def close(self) -> None:
# ----------------------------------------------------------------------------
+class PatternRemapFilter(logging.Filter):
+ """Remappe le niveau de log des records dont le message contient un pattern configuré."""
+
+ _LEVEL_MAP = {
+ 'DEBUG': logging.DEBUG,
+ 'INFO': logging.INFO,
+ 'WARNING': logging.WARNING,
+ 'ERROR': logging.ERROR,
+ }
+
+ def __init__(self, entries: list) -> None:
+ super().__init__()
+ self._rules = [
+ (e['pattern'], e['level'].upper())
+ for e in entries
+ if e.get('enabled', True) and e.get('pattern', '').strip()
+ ]
+
+ def filter(self, record: logging.LogRecord) -> bool:
+ msg = record.getMessage()
+ for pattern, level in self._rules:
+ if pattern in msg:
+ if level == 'DROP':
+ return False
+ target = self._LEVEL_MAP.get(level)
+ if target is not None:
+ record.levelno = target
+ record.levelname = level
+ return True
+ return True
+
+# ----------------------------------------------------------------------------
+
def get_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description='TVRemote Daemon for Jeedom plugin')
parser.add_argument("--loglevel", help="Log Level for the daemon", type=str)
parser.add_argument("--tvloglevel", help="Log Level for TV libraries (zeroconf, androidtvremote2, adb_shell)", type=str, default='daemon')
+ parser.add_argument("--logfiltersenabled", help="Enable log filters", type=str, default='0')
parser.add_argument("--pluginversion", help="Plugin Version", type=str)
parser.add_argument("--socketport", help="Port for TVRemote server", type=str)
parser.add_argument("--cyclefactor", help="Cycle Factor", type=str)
@@ -1598,6 +1632,25 @@ def shutdown() -> None:
logging.getLogger('androidtvremote2').setLevel(_tv_level)
logging.getLogger('adb_shell').setLevel(_tv_level)
+if config.log_filters_enabled_arg != '0':
+ config.log_filters_enabled = True
+
+if config.log_filters_enabled:
+ try:
+ with open(config.log_filters_file_path, 'r', encoding='utf-8') as _f:
+ config.log_filters = json.load(_f)
+ except FileNotFoundError:
+ logging.warning('[DAEMON][LOGFILTERS] Fichier introuvable : %s', config.log_filters_file_path)
+ except Exception as _e:
+ logging.warning('[DAEMON][LOGFILTERS] Erreur lecture filtres : %s', _e)
+
+if config.log_filters_enabled and config.log_filters:
+ _remap_filter = PatternRemapFilter(config.log_filters)
+ for _handler in logging.root.handlers:
+ _handler.addFilter(_remap_filter)
+ _active_count = sum(1 for r in config.log_filters if r.get('enabled', True))
+ logging.info('[DAEMON][LOGFILTERS] %d filtre(s) actif(s) sur %d', _active_count, len(config.log_filters))
+
try:
_LOGGER.info('[DAEMON] Starting Daemon')
_LOGGER.info('[DAEMON] Plugin Version: %s', config.plugin_version)
From 07ffc2639df5033d1593d30dc0f6bdc4393e7f4a Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sat, 20 Jun 2026 18:26:21 +0200
Subject: [PATCH 02/10] Log log filter status and rule count on startup
Add an info log entry that reports whether log filters are enabled and the number of configured filter rules during daemon startup. This makes it easier to debug and verify the daemon's logging/filter configuration at launch.
---
resources/tvremoted/tvremoted.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/resources/tvremoted/tvremoted.py b/resources/tvremoted/tvremoted.py
index 085a313..11a3727 100644
--- a/resources/tvremoted/tvremoted.py
+++ b/resources/tvremoted/tvremoted.py
@@ -1657,6 +1657,7 @@ def shutdown() -> None:
_LOGGER.info('[DAEMON] Pairing Name: %s', config.client_name)
_LOGGER.info('[DAEMON] Log Level: %s', config.log_level)
_LOGGER.info('[DAEMON] TV Log Level: %s', config.tv_log_level)
+ _LOGGER.info('[DAEMON] Log Filters Enabled: %s | rules: %d', config.log_filters_enabled, len(config.log_filters))
_LOGGER.info('[DAEMON] Socket Port: %s', config.socket_port)
_LOGGER.info('[DAEMON] Socket Host: %s', config.socket_host)
_LOGGER.info('[DAEMON] Cycle Factor: %s', config.cycle_factor)
From 3f4dc1e378be04d85ef3047d54fcbf01eb49ccd3 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sat, 20 Jun 2026 18:28:40 +0200
Subject: [PATCH 03/10] Add restart notice to filters saved alert
Update the success alert in desktop/js/logfilters.tvremote.js (window.initLogFilters) to inform the user that they must restart the daemon for saved log filter changes to take effect. This clarifies required follow-up action after saving filters.
---
desktop/js/logfilters.tvremote.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/desktop/js/logfilters.tvremote.js b/desktop/js/logfilters.tvremote.js
index 5d3df35..4529a9f 100644
--- a/desktop/js/logfilters.tvremote.js
+++ b/desktop/js/logfilters.tvremote.js
@@ -137,7 +137,7 @@ window.initLogFilters = function(data) {
jeedomUtils.showAlert({ message: data.result, level: 'danger' })
return
}
- jeedomUtils.showAlert({ message: '{{Filtres sauvegardés}}', level: 'success' })
+ jeedomUtils.showAlert({ message: '{{Filtres sauvegardés}} — {{Redémarrez le démon pour appliquer les changements}}', level: 'success' })
}
})
})
From 1440b2e9dfbaf787e7eb44b21b6ff69094389b12 Mon Sep 17 00:00:00 2001
From: TiTidom-RC <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sat, 20 Jun 2026 16:49:09 +0000
Subject: [PATCH 04/10] Auto update translation done by
Mips2648/plugins-translations workflow
---
core/i18n/de_DE.json | 27 ++++++++++++++++++++++++++-
core/i18n/en_US.json | 27 ++++++++++++++++++++++++++-
core/i18n/es_ES.json | 27 ++++++++++++++++++++++++++-
core/i18n/it_IT.json | 27 ++++++++++++++++++++++++++-
core/i18n/pt_PT.json | 27 ++++++++++++++++++++++++++-
5 files changed, 130 insertions(+), 5 deletions(-)
diff --git a/core/i18n/de_DE.json b/core/i18n/de_DE.json
index 28d1871..cba1cf5 100644
--- a/core/i18n/de_DE.json
+++ b/core/i18n/de_DE.json
@@ -1,7 +1,8 @@
{
"plugins\/tvremote\/core\/ajax\/tvremote.ajax.php": {
"401 - Accès non autorisé": "401 - Unberechtigter Zugriff",
- "Aucune méthode correspondante à": "Keine passende Methode zu"
+ "Aucune méthode correspondante à": "Keine passende Methode zu",
+ "Format de données invalide": "Ungültiges Datenformat"
},
"plugins\/tvremote\/core\/class\/tvremote.class.php": {
"0": "0",
@@ -36,6 +37,7 @@
"HDMI 3": "HDMI 3",
"HDMI 4": "HDMI 4",
"Home": "Home",
+ "Impossible d\\'enregistrer le fichier logfilters.json": "Die Datei „logfilters.json“ kann nicht gespeichert werden",
"Impossible de lancer le démon, vérifiez le log": "Der Dämon kann nicht gestartet werden, überprüfen Sie das Log",
"Info": "Info",
"Input": "Input",
@@ -84,6 +86,13 @@
"plugins\/tvremote\/core\/php\/jeetvremote.php": {
"Vous n\\'etes pas autorisé à effectuer cette action": "Sie sind nicht berechtigt, diese Aktion durchzuführen"
},
+ "plugins\/tvremote\/desktop\/js\/logfilters.tvremote.js": {
+ "Erreur lors de la sauvegarde": "Fehler beim Speichern",
+ "Ex: Cannot connect (device may be offline)": "Beispiel: Verbindung nicht möglich (Gerät ist möglicherweise offline)",
+ "Filtres sauvegardés": "Gespeicherte Filter",
+ "Redémarrez le démon pour appliquer les changements": "Starten Sie den Daemon neu, um die Änderungen zu übernehmen",
+ "Supprimer": "Löschen"
+ },
"plugins\/tvremote\/desktop\/js\/tvremote.js": {
"ADB Shell": "ADB-Shell",
"Afficher": "Anzeigen",
@@ -116,6 +125,18 @@
"Échec de l'appairage ADB pour": "Fehler beim ADB-Pairing für",
"Échec de l'appairage TVRemote pour": "Fehler beim Koppeln von TVRemote für"
},
+ "plugins\/tvremote\/desktop\/modal\/logfilters.tvremote.php": {
+ "401 - Accès non autorisé": "401 - Unberechtigter Zugriff",
+ "Actif": "Aktiv",
+ "Ajouter": "Hinzufügen",
+ "Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez\/décochez pour activer\/désactiver une règle sans la perdre.": "Legen Sie die abzufangenden Muster und die anzuwendende Protokollierungsstufe fest. Aktivieren oder deaktivieren Sie das Kontrollkästchen, um eine Regel zu aktivieren bzw. zu deaktivieren, ohne sie zu verlieren.",
+ "Niveau cible": "Zielniveau",
+ "Pattern (sous-chaîne du message de log)": "Muster (Teilzeichenfolge der Protokollmeldung)",
+ "Sauvegarder": "Speichern",
+ "Suggestions :": "Vorschläge:",
+ "Tout activer": "Alles aktivieren",
+ "Tout désactiver": "Alles deaktivieren"
+ },
"plugins\/tvremote\/desktop\/php\/tvremote.php": {
"401 - Accès non autorisé": "401 - Unberechtigter Zugriff",
"ADB": "ADB",
@@ -196,6 +217,8 @@
"Vous disposez de 5 minutes pour entrer le code après avoir cliqué sur Appairer.": "Sie haben nach dem Klicken auf „Koppeln“ 5 Minuten Zeit, um den Code einzugeben."
},
"plugins\/tvremote\/plugin_info\/configuration.php": {
+ "Active la personnalisation des niveaux de log. Les filtres sont définis dans la fenêtre de gestion dédiée.": "Aktiviert die Anpassung der Protokollstufen. Die Filter werden im entsprechenden Verwaltungsfenster definiert.",
+ "Activer les filtres de logs": "Log-Filter aktivieren",
"Certificat ADB": "ADB-Zertifikat",
"Certificat TVRemote": "TVRemote-Zertifikat",
"Cocher cette case désactivera les messages de mise à jour du plugin dans le centre de message": "Wenn Sie dieses Kästchen ankreuzen, werden die Update-Meldungen des Plugins im Nachrichtencenter deaktiviert.",
@@ -206,10 +229,12 @@
"Désactiver les messages de MàJ": "Update-Meldungen deaktivieren",
"Error": "Fehler",
"Facteur multiplicateur des cycles du démon (Défaut = x1)": "Multiplikationsfaktor der Dämonenzyklen (Standard = x1)",
+ "Filtres de logs": "Protokollfilter",
"Force la réinitialisation de PyEnv": "Erzwingt das Zurücksetzen von PyEnv",
"Force la réinitialisation de Venv": "Erzwingt das Zurücksetzen von Venv",
"Force les mises à jour Systèmes": "Erzwingt Aktualisierungen Systeme",
"Fréquence des cycles": "Häufigkeit der Zyklen",
+ "Gérer les filtres": "Filter verwalten",
"Identique au démon (défaut)": "Identisch mit dem Daemon (Standard)",
"Info": "Info",
"Le démon devra être redémarré après cette action": "Der Daemon muss nach dieser Aktion neu gestartet werden.",
diff --git a/core/i18n/en_US.json b/core/i18n/en_US.json
index 979125c..8ef8d12 100644
--- a/core/i18n/en_US.json
+++ b/core/i18n/en_US.json
@@ -1,7 +1,8 @@
{
"plugins\/tvremote\/core\/ajax\/tvremote.ajax.php": {
"401 - Accès non autorisé": "401 - Unauthorized access",
- "Aucune méthode correspondante à": "No corresponding method for"
+ "Aucune méthode correspondante à": "No corresponding method for",
+ "Format de données invalide": "Invalid data format"
},
"plugins\/tvremote\/core\/class\/tvremote.class.php": {
"0": "0",
@@ -36,6 +37,7 @@
"HDMI 3": "HDMI 3",
"HDMI 4": "HDMI 4",
"Home": "Home",
+ "Impossible d\\'enregistrer le fichier logfilters.json": "Unable to save the logfilters.json file",
"Impossible de lancer le démon, vérifiez le log": "Unable to start daemon, check log",
"Info": "Info",
"Input": "Input",
@@ -84,6 +86,13 @@
"plugins\/tvremote\/core\/php\/jeetvremote.php": {
"Vous n\\'etes pas autorisé à effectuer cette action": "You are not authorized to perform this action"
},
+ "plugins\/tvremote\/desktop\/js\/logfilters.tvremote.js": {
+ "Erreur lors de la sauvegarde": "Error while saving",
+ "Ex: Cannot connect (device may be offline)": "Example: Cannot connect (device may be offline)",
+ "Filtres sauvegardés": "Saved filters",
+ "Redémarrez le démon pour appliquer les changements": "Restart the daemon to apply the changes",
+ "Supprimer": "Delete"
+ },
"plugins\/tvremote\/desktop\/js\/tvremote.js": {
"ADB Shell": "ADB Shell",
"Afficher": "Display",
@@ -116,6 +125,18 @@
"Échec de l'appairage ADB pour": "ADB pairing failed for",
"Échec de l'appairage TVRemote pour": "TVRemote pairing failed for"
},
+ "plugins\/tvremote\/desktop\/modal\/logfilters.tvremote.php": {
+ "401 - Accès non autorisé": "401 - Unauthorized access",
+ "Actif": "Active",
+ "Ajouter": "Add",
+ "Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez\/décochez pour activer\/désactiver une règle sans la perdre.": "Define the patterns to intercept and the logging level to apply. Check or uncheck the box to enable or disable a rule without losing it.",
+ "Niveau cible": "Target level",
+ "Pattern (sous-chaîne du message de log)": "Pattern (substring of the log message)",
+ "Sauvegarder": "Save",
+ "Suggestions :": "Suggestions:",
+ "Tout activer": "Turn everything on",
+ "Tout désactiver": "Turn everything off"
+ },
"plugins\/tvremote\/desktop\/php\/tvremote.php": {
"401 - Accès non autorisé": "401 - Unauthorized access",
"ADB": "ADB",
@@ -196,6 +217,8 @@
"Vous disposez de 5 minutes pour entrer le code après avoir cliqué sur Appairer.": "You have 5 minutes to enter the code after clicking Pair."
},
"plugins\/tvremote\/plugin_info\/configuration.php": {
+ "Active la personnalisation des niveaux de log. Les filtres sont définis dans la fenêtre de gestion dédiée.": "Active customization of log levels. Filters are defined in the dedicated management window.",
+ "Activer les filtres de logs": "Enable log filters",
"Certificat ADB": "ADB certificate",
"Certificat TVRemote": "TVRemote certificate",
"Cocher cette case désactivera les messages de mise à jour du plugin dans le centre de message": "Checking this box will disable plugin update messages in the message center.",
@@ -206,10 +229,12 @@
"Désactiver les messages de MàJ": "Disable update messages",
"Error": "Error",
"Facteur multiplicateur des cycles du démon (Défaut = x1)": "Demon cycle multiplication factor (Default = x1)",
+ "Filtres de logs": "Log filters",
"Force la réinitialisation de PyEnv": "Force PyEnv reset",
"Force la réinitialisation de Venv": "Force reset Venv",
"Force les mises à jour Systèmes": "Force system updates",
"Fréquence des cycles": "Cycle frequency",
+ "Gérer les filtres": "Manage filters",
"Identique au démon (défaut)": "Same as the (default) daemon",
"Info": "Info",
"Le démon devra être redémarré après cette action": "The daemon will need to be restarted after this action.",
diff --git a/core/i18n/es_ES.json b/core/i18n/es_ES.json
index 81794e2..82f6449 100644
--- a/core/i18n/es_ES.json
+++ b/core/i18n/es_ES.json
@@ -1,7 +1,8 @@
{
"plugins\/tvremote\/core\/ajax\/tvremote.ajax.php": {
"401 - Accès non autorisé": "401 - Acceso no autorizado",
- "Aucune méthode correspondante à": "Ningún método correspondiente a"
+ "Aucune méthode correspondante à": "Ningún método correspondiente a",
+ "Format de données invalide": "Formato de datos no válido"
},
"plugins\/tvremote\/core\/class\/tvremote.class.php": {
"0": "0",
@@ -36,6 +37,7 @@
"HDMI 3": "HDMI 3",
"HDMI 4": "HDMI 4",
"Home": "Inicio",
+ "Impossible d\\'enregistrer le fichier logfilters.json": "No se puede guardar el archivo logfilters.json",
"Impossible de lancer le démon, vérifiez le log": "No se puede iniciar el demonio, compruebe el registro",
"Info": "Información",
"Input": "Entrada",
@@ -84,6 +86,13 @@
"plugins\/tvremote\/core\/php\/jeetvremote.php": {
"Vous n\\'etes pas autorisé à effectuer cette action": "No está autorizado a realizar esta acción"
},
+ "plugins\/tvremote\/desktop\/js\/logfilters.tvremote.js": {
+ "Erreur lors de la sauvegarde": "Error al guardar",
+ "Ex: Cannot connect (device may be offline)": "Ej.: No se puede conectar (es posible que el dispositivo esté desconectado)",
+ "Filtres sauvegardés": "Filtros guardados",
+ "Redémarrez le démon pour appliquer les changements": "Reinicia el demonio para aplicar los cambios",
+ "Supprimer": "Borrar"
+ },
"plugins\/tvremote\/desktop\/js\/tvremote.js": {
"ADB Shell": "ADB Shell",
"Afficher": "Ver",
@@ -116,6 +125,18 @@
"Échec de l'appairage ADB pour": "Error al emparejar ADB para",
"Échec de l'appairage TVRemote pour": "Error al emparejar TVRemote para"
},
+ "plugins\/tvremote\/desktop\/modal\/logfilters.tvremote.php": {
+ "401 - Accès non autorisé": "401 - Acceso no autorizado",
+ "Actif": "Activo",
+ "Ajouter": "Añadir",
+ "Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez\/décochez pour activer\/désactiver une règle sans la perdre.": "Define los patrones que se deben interceptar y el nivel de registro que se debe aplicar. Marca o desmarca la casilla para activar o desactivar una regla sin perderla.",
+ "Niveau cible": "Nivel objetivo",
+ "Pattern (sous-chaîne du message de log)": "Patrón (subcadena del mensaje de registro)",
+ "Sauvegarder": "Guardar",
+ "Suggestions :": "Sugerencias:",
+ "Tout activer": "Activar todo",
+ "Tout désactiver": "Desactivarlo todo"
+ },
"plugins\/tvremote\/desktop\/php\/tvremote.php": {
"401 - Accès non autorisé": "401 - Acceso no autorizado",
"ADB": "ADB",
@@ -196,6 +217,8 @@
"Vous disposez de 5 minutes pour entrer le code après avoir cliqué sur Appairer.": "Tienes 5 minutos para introducir el código después de hacer clic en Emparejar."
},
"plugins\/tvremote\/plugin_info\/configuration.php": {
+ "Active la personnalisation des niveaux de log. Les filtres sont définis dans la fenêtre de gestion dédiée.": "Activa la personalización de los niveles de registro. Los filtros se definen en la ventana de gestión correspondiente.",
+ "Activer les filtres de logs": "Activar los filtros de registros",
"Certificat ADB": "Certificado ADB",
"Certificat TVRemote": "Certificado TVRemote",
"Cocher cette case désactivera les messages de mise à jour du plugin dans le centre de message": "Al marcar esta casilla, se desactivarán los mensajes de actualización del complemento en el centro de mensajes.",
@@ -206,10 +229,12 @@
"Désactiver les messages de MàJ": "Desactivar los mensajes de actualización",
"Error": "Error",
"Facteur multiplicateur des cycles du démon (Défaut = x1)": "Factor de multiplicación del ciclo Demon (Por defecto = x1)",
+ "Filtres de logs": "Filtros de registros",
"Force la réinitialisation de PyEnv": "Forzar reinicio de PyEnv",
"Force la réinitialisation de Venv": "Forzar reinicio de Venv",
"Force les mises à jour Systèmes": "Forzar actualizaciones del sistema",
"Fréquence des cycles": "Frecuencia de ciclo",
+ "Gérer les filtres": "Gestionar los filtros",
"Identique au démon (défaut)": "Igual que el demonio (por defecto)",
"Info": "Información",
"Le démon devra être redémarré après cette action": "El demonio deberá reiniciarse después de esta acción.",
diff --git a/core/i18n/it_IT.json b/core/i18n/it_IT.json
index 2e04eaa..74e7e39 100644
--- a/core/i18n/it_IT.json
+++ b/core/i18n/it_IT.json
@@ -1,7 +1,8 @@
{
"plugins\/tvremote\/core\/ajax\/tvremote.ajax.php": {
"401 - Accès non autorisé": "401 - Accesso non autorizzato",
- "Aucune méthode correspondante à": "Nessun metodo corrispondente a"
+ "Aucune méthode correspondante à": "Nessun metodo corrispondente a",
+ "Format de données invalide": "Formato dati non valido"
},
"plugins\/tvremote\/core\/class\/tvremote.class.php": {
"0": "0",
@@ -36,6 +37,7 @@
"HDMI 3": "HDMI 3",
"HDMI 4": "HDMI 4",
"Home": "Casa",
+ "Impossible d\\'enregistrer le fichier logfilters.json": "Impossibile salvare il file logfilters.json",
"Impossible de lancer le démon, vérifiez le log": "Impossibile avviare il demone, controllare il registro",
"Info": "Info",
"Input": "Ingresso",
@@ -84,6 +86,13 @@
"plugins\/tvremote\/core\/php\/jeetvremote.php": {
"Vous n\\'etes pas autorisé à effectuer cette action": "Non siete autorizzati ad eseguire questa azione"
},
+ "plugins\/tvremote\/desktop\/js\/logfilters.tvremote.js": {
+ "Erreur lors de la sauvegarde": "Errore durante il salvataggio",
+ "Ex: Cannot connect (device may be offline)": "Es.: Impossibile connettersi (il dispositivo potrebbe essere offline)",
+ "Filtres sauvegardés": "Filtri salvati",
+ "Redémarrez le démon pour appliquer les changements": "Riavviare il demone per applicare le modifiche",
+ "Supprimer": "Cancellare"
+ },
"plugins\/tvremote\/desktop\/js\/tvremote.js": {
"ADB Shell": "ADB Shell",
"Afficher": "Vista",
@@ -116,6 +125,18 @@
"Échec de l'appairage ADB pour": "Errore nell'accoppiamento ADB per",
"Échec de l'appairage TVRemote pour": "Errore nell'accoppiamento TVRemote per"
},
+ "plugins\/tvremote\/desktop\/modal\/logfilters.tvremote.php": {
+ "401 - Accès non autorisé": "401 - Accesso non autorizzato",
+ "Actif": "Attivo",
+ "Ajouter": "Aggiungi",
+ "Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez\/décochez pour activer\/désactiver une règle sans la perdre.": "Definisci i modelli da intercettare e il livello di registrazione da applicare. Seleziona\/deseleziona per attivare\/disattivare una regola senza perderla.",
+ "Niveau cible": "Livello previsto",
+ "Pattern (sous-chaîne du message de log)": "Pattern (sottostringa del messaggio di log)",
+ "Sauvegarder": "Risparmiare",
+ "Suggestions :": "Suggerimenti:",
+ "Tout activer": "Attiva tutto",
+ "Tout désactiver": "Disattiva tutto"
+ },
"plugins\/tvremote\/desktop\/php\/tvremote.php": {
"401 - Accès non autorisé": "401 - Accesso non autorizzato",
"ADB": "ADB",
@@ -196,6 +217,8 @@
"Vous disposez de 5 minutes pour entrer le code après avoir cliqué sur Appairer.": "Hai 5 minuti di tempo per inserire il codice dopo aver cliccato su Accoppia."
},
"plugins\/tvremote\/plugin_info\/configuration.php": {
+ "Active la personnalisation des niveaux de log. Les filtres sont définis dans la fenêtre de gestion dédiée.": "Attiva la personalizzazione dei livelli di registrazione. I filtri vengono definiti nella finestra di gestione dedicata.",
+ "Activer les filtres de logs": "Attivare i filtri dei log",
"Certificat ADB": "Certificato ADB",
"Certificat TVRemote": "Certificato TVRemote",
"Cocher cette case désactivera les messages de mise à jour du plugin dans le centre de message": "Selezionando questa casella, i messaggi di aggiornamento del plugin nel centro messaggi saranno disattivati.",
@@ -206,10 +229,12 @@
"Désactiver les messages de MàJ": "Disattivare i messaggi di aggiornamento",
"Error": "Errore",
"Facteur multiplicateur des cycles du démon (Défaut = x1)": "Fattore di moltiplicazione dei cicli demonici (default = x1)",
+ "Filtres de logs": "Filtri dei log",
"Force la réinitialisation de PyEnv": "Forza il reset di PyEnv",
"Force la réinitialisation de Venv": "Ripristino forzato di Venv",
"Force les mises à jour Systèmes": "Forzare gli aggiornamenti del sistema",
"Fréquence des cycles": "Frequenza del ciclo",
+ "Gérer les filtres": "Gestisci i filtri",
"Identique au démon (défaut)": "Identico al demone (predefinito)",
"Info": "Info",
"Le démon devra être redémarré après cette action": "Il demone dovrà essere riavviato dopo questa operazione.",
diff --git a/core/i18n/pt_PT.json b/core/i18n/pt_PT.json
index a5522ec..854e302 100644
--- a/core/i18n/pt_PT.json
+++ b/core/i18n/pt_PT.json
@@ -1,7 +1,8 @@
{
"plugins\/tvremote\/core\/ajax\/tvremote.ajax.php": {
"401 - Accès non autorisé": "401 - Acesso não autorizado",
- "Aucune méthode correspondante à": "Nenhum método correspondente a"
+ "Aucune méthode correspondante à": "Nenhum método correspondente a",
+ "Format de données invalide": "Formato de dados inválido"
},
"plugins\/tvremote\/core\/class\/tvremote.class.php": {
"0": "0",
@@ -36,6 +37,7 @@
"HDMI 3": "HDMI 3",
"HDMI 4": "HDMI 4",
"Home": "Casa",
+ "Impossible d\\'enregistrer le fichier logfilters.json": "Não é possível guardar o ficheiro logfilters.json",
"Impossible de lancer le démon, vérifiez le log": "Não é possível iniciar o daemon, verificar o registo",
"Info": "Informação",
"Input": "Entrada",
@@ -84,6 +86,13 @@
"plugins\/tvremote\/core\/php\/jeetvremote.php": {
"Vous n\\'etes pas autorisé à effectuer cette action": "Não está autorizado a efetuar esta ação"
},
+ "plugins\/tvremote\/desktop\/js\/logfilters.tvremote.js": {
+ "Erreur lors de la sauvegarde": "Erro ao guardar",
+ "Ex: Cannot connect (device may be offline)": "Ex.: Não é possível estabelecer ligação (o dispositivo pode estar offline)",
+ "Filtres sauvegardés": "Filtros guardados",
+ "Redémarrez le démon pour appliquer les changements": "Reinicie o daemon para aplicar as alterações",
+ "Supprimer": "Eliminar"
+ },
"plugins\/tvremote\/desktop\/js\/tvremote.js": {
"ADB Shell": "ADB Shell",
"Afficher": "Ver",
@@ -116,6 +125,18 @@
"Échec de l'appairage ADB pour": "Falha no emparelhamento ADB para",
"Échec de l'appairage TVRemote pour": "Falha no emparelhamento do TVRemote para"
},
+ "plugins\/tvremote\/desktop\/modal\/logfilters.tvremote.php": {
+ "401 - Accès non autorisé": "401 - Acesso não autorizado",
+ "Actif": "Ativo",
+ "Ajouter": "Adicionar",
+ "Définissez les patterns à intercepter et le niveau de log à appliquer. Cochez\/décochez pour activer\/désactiver une règle sans la perdre.": "Defina os padrões a interceptar e o nível de registo a aplicar. Assinale\/desassinale para ativar\/desativar uma regra sem a perder.",
+ "Niveau cible": "Nível pretendido",
+ "Pattern (sous-chaîne du message de log)": "Padrão (subcadeia da mensagem de registo)",
+ "Sauvegarder": "Guardar",
+ "Suggestions :": "Sugestões:",
+ "Tout activer": "Ativar tudo",
+ "Tout désactiver": "Desativar tudo"
+ },
"plugins\/tvremote\/desktop\/php\/tvremote.php": {
"401 - Accès non autorisé": "401 - Acesso não autorizado",
"ADB": "ADB",
@@ -196,6 +217,8 @@
"Vous disposez de 5 minutes pour entrer le code après avoir cliqué sur Appairer.": "Tem 5 minutos para introduzir o código depois de clicar em Emparelhar."
},
"plugins\/tvremote\/plugin_info\/configuration.php": {
+ "Active la personnalisation des niveaux de log. Les filtres sont définis dans la fenêtre de gestion dédiée.": "Ativa a personalização dos níveis de registo. Os filtros são definidos na janela de gestão dedicada.",
+ "Activer les filtres de logs": "Ativar os filtros de registos",
"Certificat ADB": "Certificado ADB",
"Certificat TVRemote": "Certificado TVRemote",
"Cocher cette case désactivera les messages de mise à jour du plugin dans le centre de message": "Marcar esta caixa desativará as mensagens de atualização do plugin no centro de mensagens.",
@@ -206,10 +229,12 @@
"Désactiver les messages de MàJ": "Desativar mensagens de atualização",
"Error": "Erro",
"Facteur multiplicateur des cycles du démon (Défaut = x1)": "Fator de multiplicação do ciclo de demonstração (Predefinição = x1)",
+ "Filtres de logs": "Filtros de registos",
"Force la réinitialisation de PyEnv": "Forçar reinicialização do PyEnv",
"Force la réinitialisation de Venv": "Forçar a reposição do Venv",
"Force les mises à jour Systèmes": "Forçar actualizações do sistema",
"Fréquence des cycles": "Frequência do ciclo",
+ "Gérer les filtres": "Gerir os filtros",
"Identique au démon (défaut)": "Idêntico ao daemon (padrão)",
"Info": "Informação",
"Le démon devra être redémarré après cette action": "O daemon deverá ser reiniciado após esta ação.",
From 37e43561656ee64656bb7132275c964ed3588518 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sat, 20 Jun 2026 18:59:48 +0200
Subject: [PATCH 05/10] Add blank line for readability in config.py
Introduce a blank line between the log_filters_file_path definition and the remote lists to improve code readability. No functional changes.
---
resources/tvremoted/config.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/resources/tvremoted/config.py b/resources/tvremoted/config.py
index fed6b02..9550359 100644
--- a/resources/tvremoted/config.py
+++ b/resources/tvremoted/config.py
@@ -29,6 +29,7 @@ def __init__(self, **kwargs):
self.log_filters_enabled: bool = False
self.log_filters: list = [] # [{ "pattern": str, "level": str, "enabled": bool }]
self.log_filters_file_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'data/filters/logfilters.json'))
+
self.remote_mac_adb = [] # MAC addresses for ADB
self.remote_names = [] # Names for AndroidTVRemote2
self.remote_names_adb = [] # Names for ADB
From 9688f78d0dd0e93b97d91b5e22f17eb174e83481 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sun, 21 Jun 2026 09:28:29 +0200
Subject: [PATCH 06/10] Bump version and lower notification log level
Update plugin version to 1.4.1 and reduce log verbosity in tvremoted: change several notification logs (is_available, is_on, current_app, volume_info) from INFO to DEBUG, and switch an on-demand ADB connection log to DEBUG to reduce noise during normal operation. Files changed: plugin_info/info.json, resources/tvremoted/tvremoted.py.
---
plugin_info/info.json | 2 +-
resources/tvremoted/tvremoted.py | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/plugin_info/info.json b/plugin_info/info.json
index 82c34c8..3c6f800 100644
--- a/plugin_info/info.json
+++ b/plugin_info/info.json
@@ -1,7 +1,7 @@
{
"id": "tvremote",
"name": "TV Remote",
- "pluginVersion": "1.4.0",
+ "pluginVersion": "1.4.1",
"description": {
"fr_FR": "Plugin pour contrôler les équipements Android de type Télévision (Sony, Nvidia Shield, Freebox TV, etc...) via le service de télécommande Google (TVRemote) ou via ADB. Il permet de contrôler les différentes fonctions de sa télévision (power, volume, entrées HDMI, lancement d'applications, chaînes TV, navigation dans l'interface, etc...)",
"en_US": "Plugin to control Android TV devices (Sony, Nvidia Shield, Freebox TV, etc...) via Google remote control service (TVRemote) or via ADB. It allows you to control various functions of your TV (power, volume, HDMI inputs, launching applications, TV channels, navigating the interface, etc...)",
diff --git a/resources/tvremoted/tvremoted.py b/resources/tvremoted/tvremoted.py
index 11a3727..5995efa 100644
--- a/resources/tvremoted/tvremoted.py
+++ b/resources/tvremoted/tvremoted.py
@@ -171,7 +171,7 @@ async def main(self) -> None:
self._logger.debug(traceback.format_exc())
def is_available_updated(is_available: bool) -> None:
- self._logger.info("[EQRemote][Is_Available][%s] Notification :: %s", self._macAddr, is_available)
+ self._logger.debug("[EQRemote][Is_Available][%s] Notification :: %s", self._macAddr, is_available)
try:
# UpdateLastTime
currentTime = int(time.time())
@@ -193,7 +193,7 @@ def is_available_updated(is_available: bool) -> None:
self._logger.debug(traceback.format_exc())
def is_on_updated(is_on: bool) -> None:
- self._logger.info("[EQRemote][Is_On][%s] Notification :: %s", self._macAddr, is_on)
+ self._logger.debug("[EQRemote][Is_On][%s] Notification :: %s", self._macAddr, is_on)
try:
# UpdateLastTime
currentTime = int(time.time())
@@ -215,7 +215,7 @@ def is_on_updated(is_on: bool) -> None:
self._logger.debug(traceback.format_exc())
def current_app_updated(current_app: str) -> None:
- self._logger.info("[EQRemote][Current_App][%s] Notification :: %s", self._macAddr, current_app)
+ self._logger.debug("[EQRemote][Current_App][%s] Notification :: %s", self._macAddr, current_app)
try:
# UpdateLastTime
currentTime = int(time.time())
@@ -236,7 +236,7 @@ def current_app_updated(current_app: str) -> None:
self._logger.debug(traceback.format_exc())
def volume_info_updated(volume_info: VolumeInfo) -> None:
- self._logger.info("[EQRemote][Volume_Info][%s] Notification :: %s", self._macAddr, volume_info)
+ self._logger.debug("[EQRemote][Volume_Info][%s] Notification :: %s", self._macAddr, volume_info)
try:
# UpdateLastTime
currentTime = int(time.time())
@@ -690,7 +690,7 @@ async def send_command(self, action: str | None = None, value: str | None = None
# Connect on-demand if not already connected
if not self._persistent_connection and not self._connected:
- self._logger.info("[EQRemoteADB][SendCommand] On-demand mode: connecting...")
+ self._logger.debug("[EQRemoteADB][SendCommand] On-demand mode: connecting...")
if self._adb is None:
self._adb = AdbDeviceTcpAsync(self._host, self._port, default_transport_timeout_s=self._config.adb_timeout)
From debdce6625177577cbc9c57b74f30675f56d261f Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sun, 21 Jun 2026 09:46:09 +0200
Subject: [PATCH 07/10] Limit CI workflows to relevant file changes
Add path filters to pull_request triggers so workflows only run for relevant files on the beta branch. checkPHP.yml and checkPHPCompat.yml now include '**/*.php', and checkPython.yml includes 'resources/**/*.py'. This reduces unnecessary CI runs and conserves resources by running language-specific checks only when corresponding files change.
---
.github/workflows/checkPHP.yml | 2 ++
.github/workflows/checkPHPCompat.yml | 2 ++
.github/workflows/checkPython.yml | 2 ++
3 files changed, 6 insertions(+)
diff --git a/.github/workflows/checkPHP.yml b/.github/workflows/checkPHP.yml
index eae9699..6960f0e 100644
--- a/.github/workflows/checkPHP.yml
+++ b/.github/workflows/checkPHP.yml
@@ -4,6 +4,8 @@ on:
pull_request:
branches:
- beta
+ paths:
+ - '**/*.php'
jobs:
php-lint:
diff --git a/.github/workflows/checkPHPCompat.yml b/.github/workflows/checkPHPCompat.yml
index 6c9e618..a10c94c 100644
--- a/.github/workflows/checkPHPCompat.yml
+++ b/.github/workflows/checkPHPCompat.yml
@@ -4,6 +4,8 @@ on:
pull_request:
branches:
- beta
+ paths:
+ - '**/*.php'
jobs:
php-compat:
diff --git a/.github/workflows/checkPython.yml b/.github/workflows/checkPython.yml
index 75c4024..b9ebe58 100644
--- a/.github/workflows/checkPython.yml
+++ b/.github/workflows/checkPython.yml
@@ -4,6 +4,8 @@ on:
pull_request:
branches:
- beta
+ paths:
+ - 'resources/**/*.py'
jobs:
python-check:
From be2cd763d2791ecdfdff139208c4fdbc7ef924c0 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sun, 21 Jun 2026 09:57:16 +0200
Subject: [PATCH 08/10] Add JavaScript syntax-check workflow
Introduce a GitHub Actions workflow that runs on pull requests to the beta branch when .js files change. It checks out the repo, sets up Node.js 22, and runs `node --check` on all .js files (excluding node_modules) to catch syntax errors early.
---
.github/workflows/js-check.yml | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 .github/workflows/js-check.yml
diff --git a/.github/workflows/js-check.yml b/.github/workflows/js-check.yml
new file mode 100644
index 0000000..c05a03b
--- /dev/null
+++ b/.github/workflows/js-check.yml
@@ -0,0 +1,22 @@
+name: JavaScript Syntax Check
+
+on:
+ pull_request:
+ branches:
+ - beta
+ paths:
+ - '**/*.js'
+
+jobs:
+ js-lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+
+ - name: Check JavaScript syntax
+ run: find . -name "*.js" ! -path "./node_modules/*" -exec node --check {} \;
From 26369b15e96ff38930b664e9be0433e2004e0b89 Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sun, 21 Jun 2026 10:09:17 +0200
Subject: [PATCH 09/10] Add workflow_dispatch to GitHub workflows
Enable manual runs from the Actions UI by adding workflow_dispatch to the CI workflows. Updated .github/workflows/checkPHP.yml, checkPHPCompat.yml, checkPython.yml, and js-check.yml to include the manual dispatch trigger while preserving the existing branch/path filters.
---
.github/workflows/checkPHP.yml | 1 +
.github/workflows/checkPHPCompat.yml | 1 +
.github/workflows/checkPython.yml | 1 +
.github/workflows/js-check.yml | 1 +
4 files changed, 4 insertions(+)
diff --git a/.github/workflows/checkPHP.yml b/.github/workflows/checkPHP.yml
index 6960f0e..846f197 100644
--- a/.github/workflows/checkPHP.yml
+++ b/.github/workflows/checkPHP.yml
@@ -6,6 +6,7 @@ on:
- beta
paths:
- '**/*.php'
+ workflow_dispatch:
jobs:
php-lint:
diff --git a/.github/workflows/checkPHPCompat.yml b/.github/workflows/checkPHPCompat.yml
index a10c94c..e7705ad 100644
--- a/.github/workflows/checkPHPCompat.yml
+++ b/.github/workflows/checkPHPCompat.yml
@@ -6,6 +6,7 @@ on:
- beta
paths:
- '**/*.php'
+ workflow_dispatch:
jobs:
php-compat:
diff --git a/.github/workflows/checkPython.yml b/.github/workflows/checkPython.yml
index b9ebe58..381a50f 100644
--- a/.github/workflows/checkPython.yml
+++ b/.github/workflows/checkPython.yml
@@ -6,6 +6,7 @@ on:
- beta
paths:
- 'resources/**/*.py'
+ workflow_dispatch:
jobs:
python-check:
diff --git a/.github/workflows/js-check.yml b/.github/workflows/js-check.yml
index c05a03b..ff56a74 100644
--- a/.github/workflows/js-check.yml
+++ b/.github/workflows/js-check.yml
@@ -6,6 +6,7 @@ on:
- beta
paths:
- '**/*.js'
+ workflow_dispatch:
jobs:
js-lint:
From 155172dd28846f50afacf1fcdae5357948f8cf7d Mon Sep 17 00:00:00 2001
From: Olivier <16240457+TiTidom-RC@users.noreply.github.com>
Date: Sun, 21 Jun 2026 10:18:47 +0200
Subject: [PATCH 10/10] Bump actions/setup-node to v5
Update the js-check workflow to use actions/setup-node@v5 (was @v4). This ensures the workflow uses the latest setup-node release, improving compatibility with Node.js 22 and picking up fixes and enhancements from the newer action version.
---
.github/workflows/js-check.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/js-check.yml b/.github/workflows/js-check.yml
index ff56a74..756c6a3 100644
--- a/.github/workflows/js-check.yml
+++ b/.github/workflows/js-check.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions/checkout@v6
- name: Setup Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v5
with:
node-version: '22'