688 lines
20 KiB
Python
688 lines
20 KiB
Python
"""
|
|
PC Monitor - Serveur Flask pour monitoring hardware
|
|
Supporte plusieurs plugins: LibreHardwareMonitor, HWiNFO, Plexamp, etc.
|
|
"""
|
|
from flask import Flask, render_template, jsonify, request
|
|
import json
|
|
import os
|
|
import subprocess
|
|
from threading import Thread
|
|
import time
|
|
|
|
# Import du système de plugins
|
|
from plugins import get_plugin, get_available_plugins, PLUGINS
|
|
from plugins import get_media_plugin, get_available_media_plugins, MEDIA_PLUGINS
|
|
|
|
app = Flask(__name__)
|
|
app.config['SECRET_KEY'] = 'votre-cle-secrete-ici'
|
|
|
|
# Fichiers de configuration
|
|
CONFIG_FILE = 'config.json'
|
|
|
|
# Plugins actifs (initialisés au démarrage)
|
|
active_plugin = None
|
|
plexamp_plugin = None
|
|
|
|
# Configuration par défaut
|
|
DEFAULT_CONFIG = {
|
|
"active_plugin": "librehardwaremonitor",
|
|
"theme": "dark",
|
|
"apps": [],
|
|
"apps_tab": "",
|
|
"plugins": {
|
|
"librehardwaremonitor": {
|
|
"host": "127.0.0.1",
|
|
"port": 8085
|
|
},
|
|
"hwinfo": {
|
|
"host": "127.0.0.1",
|
|
"port": 60000
|
|
}
|
|
},
|
|
"media": {
|
|
"plexamp": {
|
|
"enabled": False,
|
|
"host": "127.0.0.1",
|
|
"port": 32400,
|
|
"token": ""
|
|
}
|
|
}
|
|
}
|
|
|
|
DEFAULT_PLUGIN_CONFIG = {
|
|
"tabs": [
|
|
{
|
|
"id": "tab1",
|
|
"name": "Général",
|
|
"sensors": []
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
# ==================== Gestion de la configuration ====================
|
|
|
|
def load_config():
|
|
"""Charge la configuration globale"""
|
|
if os.path.exists(CONFIG_FILE):
|
|
try:
|
|
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
|
|
config = json.load(f)
|
|
# Fusionner avec les valeurs par défaut
|
|
for key, value in DEFAULT_CONFIG.items():
|
|
if key not in config:
|
|
config[key] = value
|
|
return config
|
|
except Exception as e:
|
|
print(f"Erreur chargement config: {e}")
|
|
return DEFAULT_CONFIG.copy()
|
|
return DEFAULT_CONFIG.copy()
|
|
|
|
|
|
def save_config(config):
|
|
"""Sauvegarde la configuration globale"""
|
|
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
|
|
json.dump(config, f, indent=2, ensure_ascii=False)
|
|
|
|
|
|
def get_plugin_config_file(plugin_id):
|
|
"""Retourne le nom du fichier de config pour un plugin"""
|
|
return f'config_{plugin_id}.json'
|
|
|
|
|
|
def load_plugin_config(plugin_id):
|
|
"""Charge la configuration spécifique à un plugin"""
|
|
config_file = get_plugin_config_file(plugin_id)
|
|
if os.path.exists(config_file):
|
|
try:
|
|
with open(config_file, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
except Exception as e:
|
|
print(f"Erreur chargement config plugin {plugin_id}: {e}")
|
|
return DEFAULT_PLUGIN_CONFIG.copy()
|
|
return DEFAULT_PLUGIN_CONFIG.copy()
|
|
|
|
|
|
def save_plugin_config(plugin_id, config):
|
|
"""Sauvegarde la configuration spécifique à un plugin"""
|
|
config_file = get_plugin_config_file(plugin_id)
|
|
with open(config_file, 'w', encoding='utf-8') as f:
|
|
json.dump(config, f, indent=2, ensure_ascii=False)
|
|
|
|
|
|
def get_merged_config():
|
|
"""
|
|
Retourne une config fusionnée (global + plugin actif)
|
|
Pour compatibilité avec le code existant
|
|
"""
|
|
global_config = load_config()
|
|
plugin_id = global_config.get('active_plugin', 'librehardwaremonitor')
|
|
plugin_config = load_plugin_config(plugin_id)
|
|
|
|
# Fusionner
|
|
merged = global_config.copy()
|
|
merged['tabs'] = plugin_config.get('tabs', [])
|
|
|
|
return merged
|
|
|
|
|
|
def save_merged_config(config):
|
|
"""
|
|
Sauvegarde une config fusionnée
|
|
Sépare les données globales et plugin
|
|
"""
|
|
global_config = load_config()
|
|
plugin_id = global_config.get('active_plugin', 'librehardwaremonitor')
|
|
|
|
# Extraire les données plugin
|
|
plugin_config = {
|
|
'tabs': config.get('tabs', [])
|
|
}
|
|
|
|
# Mettre à jour la config globale
|
|
global_config['theme'] = config.get('theme', 'dark')
|
|
global_config['apps'] = config.get('apps', [])
|
|
global_config['apps_tab'] = config.get('apps_tab', '')
|
|
|
|
# Sauvegarder les deux
|
|
save_config(global_config)
|
|
save_plugin_config(plugin_id, plugin_config)
|
|
|
|
|
|
# ==================== Gestion du plugin actif ====================
|
|
|
|
def init_plugin():
|
|
"""Initialise le plugin actif"""
|
|
global active_plugin
|
|
|
|
config = load_config()
|
|
plugin_id = config.get('active_plugin', 'librehardwaremonitor')
|
|
plugin_config = config.get('plugins', {}).get(plugin_id, {})
|
|
|
|
try:
|
|
active_plugin = get_plugin(plugin_id, plugin_config)
|
|
print(f"Plugin initialisé: {active_plugin.get_name()}")
|
|
except Exception as e:
|
|
print(f"Erreur initialisation plugin {plugin_id}: {e}")
|
|
# Fallback sur LHM
|
|
active_plugin = get_plugin('librehardwaremonitor', {'host': '127.0.0.1', 'port': 8085})
|
|
|
|
|
|
def switch_plugin(plugin_id):
|
|
"""Change le plugin actif"""
|
|
global active_plugin
|
|
|
|
config = load_config()
|
|
plugin_config = config.get('plugins', {}).get(plugin_id, {})
|
|
|
|
try:
|
|
active_plugin = get_plugin(plugin_id, plugin_config)
|
|
config['active_plugin'] = plugin_id
|
|
save_config(config)
|
|
print(f"Plugin changé: {active_plugin.get_name()}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"Erreur changement plugin: {e}")
|
|
return False
|
|
|
|
|
|
# ==================== Thread d'historique ====================
|
|
|
|
def update_history_loop():
|
|
"""Boucle pour mettre à jour l'historique des capteurs"""
|
|
global active_plugin
|
|
|
|
while True:
|
|
if active_plugin:
|
|
try:
|
|
data = active_plugin.get_data()
|
|
if data:
|
|
sensors = active_plugin.parse_sensors(data)
|
|
active_plugin.update_history(sensors)
|
|
except Exception as e:
|
|
print(f"Erreur update history: {e}")
|
|
time.sleep(1)
|
|
|
|
|
|
# ==================== Routes Pages ====================
|
|
|
|
@app.route('/')
|
|
def index():
|
|
"""Page d'accueil - redirige vers dashboard"""
|
|
return render_template('dashboard.html')
|
|
|
|
|
|
@app.route('/admin')
|
|
def admin():
|
|
"""Page d'administration"""
|
|
return render_template('admin.html')
|
|
|
|
|
|
@app.route('/dashboard')
|
|
def dashboard():
|
|
"""Page de dashboard"""
|
|
return render_template('dashboard.html')
|
|
|
|
|
|
# ==================== API Plugins ====================
|
|
|
|
@app.route('/api/plugins')
|
|
def api_plugins_list():
|
|
"""Liste des plugins disponibles"""
|
|
plugins = get_available_plugins()
|
|
config = load_config()
|
|
active_id = config.get('active_plugin', 'librehardwaremonitor')
|
|
|
|
# Ajouter l'état actif
|
|
for plugin in plugins:
|
|
plugin['active'] = plugin['id'] == active_id
|
|
plugin['config'] = config.get('plugins', {}).get(plugin['id'], {})
|
|
|
|
return jsonify(plugins)
|
|
|
|
|
|
@app.route('/api/plugins/active')
|
|
def api_plugins_active():
|
|
"""Retourne le plugin actif"""
|
|
global active_plugin
|
|
|
|
if not active_plugin:
|
|
return jsonify({'error': 'Aucun plugin actif'}), 500
|
|
|
|
config = load_config()
|
|
plugin_id = active_plugin.get_id()
|
|
|
|
return jsonify({
|
|
'id': plugin_id,
|
|
'name': active_plugin.get_name(),
|
|
'config': config.get('plugins', {}).get(plugin_id, {})
|
|
})
|
|
|
|
|
|
@app.route('/api/plugins/switch', methods=['POST'])
|
|
def api_plugins_switch():
|
|
"""Change le plugin actif"""
|
|
data = request.get_json()
|
|
plugin_id = data.get('plugin_id')
|
|
|
|
if not plugin_id or plugin_id not in PLUGINS:
|
|
return jsonify({'success': False, 'error': 'Plugin invalide'}), 400
|
|
|
|
if switch_plugin(plugin_id):
|
|
return jsonify({'success': True, 'message': f'Plugin changé: {plugin_id}'})
|
|
else:
|
|
return jsonify({'success': False, 'error': 'Erreur changement plugin'}), 500
|
|
|
|
|
|
@app.route('/api/plugins/config', methods=['POST'])
|
|
def api_plugins_config():
|
|
"""Met à jour la configuration d'un plugin"""
|
|
data = request.get_json()
|
|
plugin_id = data.get('plugin_id')
|
|
plugin_config = data.get('config', {})
|
|
|
|
if not plugin_id:
|
|
return jsonify({'success': False, 'error': 'Plugin ID requis'}), 400
|
|
|
|
config = load_config()
|
|
|
|
if 'plugins' not in config:
|
|
config['plugins'] = {}
|
|
|
|
config['plugins'][plugin_id] = plugin_config
|
|
save_config(config)
|
|
|
|
# Si c'est le plugin actif, le réinitialiser
|
|
if active_plugin and active_plugin.get_id() == plugin_id:
|
|
init_plugin()
|
|
|
|
return jsonify({'success': True, 'message': 'Configuration mise à jour'})
|
|
|
|
|
|
@app.route('/api/plugins/test', methods=['POST'])
|
|
def api_plugins_test():
|
|
"""Teste la connexion d'un plugin"""
|
|
data = request.get_json()
|
|
plugin_id = data.get('plugin_id')
|
|
plugin_config = data.get('config', {})
|
|
|
|
if not plugin_id or plugin_id not in PLUGINS:
|
|
return jsonify({'success': False, 'error': 'Plugin invalide'}), 400
|
|
|
|
try:
|
|
# Créer une instance temporaire pour tester
|
|
test_plugin = get_plugin(plugin_id, plugin_config)
|
|
result = test_plugin.test_connection()
|
|
return jsonify(result)
|
|
except Exception as e:
|
|
return jsonify({'success': False, 'error': str(e)}), 500
|
|
|
|
|
|
# ==================== API Capteurs (compatible) ====================
|
|
|
|
@app.route('/api/lhm/sensors')
|
|
def api_lhm_sensors():
|
|
"""Retourne la liste complète de tous les capteurs"""
|
|
global active_plugin
|
|
|
|
if not active_plugin:
|
|
return jsonify({"error": "Aucun plugin actif"}), 500
|
|
|
|
data = active_plugin.get_data()
|
|
if not data:
|
|
return jsonify({"error": "Impossible de récupérer les données"}), 500
|
|
|
|
sensors = active_plugin.parse_sensors(data)
|
|
|
|
# Grouper par catégorie
|
|
grouped = {}
|
|
for sensor in sensors:
|
|
category = sensor.get('category', 'Autre')
|
|
if category not in grouped:
|
|
grouped[category] = []
|
|
grouped[category].append(sensor)
|
|
|
|
return jsonify(grouped)
|
|
|
|
|
|
@app.route('/api/lhm/hierarchy')
|
|
def api_lhm_hierarchy():
|
|
"""Retourne la structure hiérarchique complète des capteurs"""
|
|
global active_plugin
|
|
|
|
if not active_plugin:
|
|
return jsonify({"error": "Aucun plugin actif"}), 500
|
|
|
|
hierarchy = active_plugin.get_hierarchy()
|
|
if not hierarchy:
|
|
return jsonify({"error": "Impossible de récupérer les données"}), 500
|
|
|
|
return jsonify(hierarchy)
|
|
|
|
|
|
@app.route('/api/lhm/data')
|
|
def api_lhm_data():
|
|
"""Retourne les données actuelles des capteurs sélectionnés"""
|
|
global active_plugin
|
|
|
|
if not active_plugin:
|
|
return jsonify({"error": "Aucun plugin actif"}), 500
|
|
|
|
config = get_merged_config()
|
|
data = active_plugin.get_data()
|
|
|
|
if not data:
|
|
return jsonify({"error": "Impossible de récupérer les données"}), 500
|
|
|
|
all_sensors = active_plugin.parse_sensors(data)
|
|
|
|
# Créer un dictionnaire pour lookup rapide
|
|
sensor_dict = {s['id']: s for s in all_sensors}
|
|
|
|
# Organiser par onglets
|
|
result = {
|
|
"tabs": [],
|
|
"timestamp": time.time()
|
|
}
|
|
|
|
for tab in config.get('tabs', []):
|
|
tab_data = {
|
|
"id": tab['id'],
|
|
"name": tab['name'],
|
|
"sensors": []
|
|
}
|
|
|
|
for sensor_config in tab.get('sensors', []):
|
|
sensor_id = sensor_config['id']
|
|
if sensor_id in sensor_dict:
|
|
sensor = sensor_dict[sensor_id].copy()
|
|
sensor['show_graph'] = sensor_config.get('show_graph', False)
|
|
sensor['viz_type'] = sensor_config.get('viz_type', 'line')
|
|
sensor['card_size'] = sensor_config.get('card_size', 'medium')
|
|
sensor['font_family'] = sensor_config.get('font_family', 'system')
|
|
sensor['font_bold'] = sensor_config.get('font_bold', True)
|
|
sensor['font_size'] = sensor_config.get('font_size', 'small')
|
|
sensor['hide_value_mobile'] = sensor_config.get('hide_value_mobile', False)
|
|
sensor['show_type_badge'] = sensor_config.get('show_type_badge', True)
|
|
sensor['gauge_options'] = sensor_config.get('gauge_options', {})
|
|
sensor['chart_options'] = sensor_config.get('chart_options', {})
|
|
tab_data['sensors'].append(sensor)
|
|
|
|
result['tabs'].append(tab_data)
|
|
|
|
return jsonify(result)
|
|
|
|
|
|
@app.route('/api/lhm/history/<path:sensor_id>')
|
|
def api_lhm_history(sensor_id):
|
|
"""Retourne l'historique d'un capteur pour le graphique"""
|
|
global active_plugin
|
|
|
|
if not active_plugin:
|
|
return jsonify({"error": "Aucun plugin actif"}), 500
|
|
|
|
# Reconstruire l'ID complet
|
|
if not sensor_id.startswith('/'):
|
|
sensor_id = '/' + sensor_id
|
|
|
|
count = request.args.get('count', 60, type=int)
|
|
history = active_plugin.get_history(sensor_id, count)
|
|
|
|
return jsonify({
|
|
"sensor_id": sensor_id,
|
|
"values": history,
|
|
"count": len(history)
|
|
})
|
|
|
|
|
|
# ==================== API Configuration ====================
|
|
|
|
@app.route('/api/config')
|
|
def api_config_get():
|
|
"""Récupère la configuration actuelle (fusionnée)"""
|
|
config = get_merged_config()
|
|
return jsonify(config)
|
|
|
|
|
|
@app.route('/api/config', methods=['POST'])
|
|
def api_config_save():
|
|
"""Sauvegarde la configuration"""
|
|
try:
|
|
config = request.get_json()
|
|
save_merged_config(config)
|
|
return jsonify({"success": True, "message": "Configuration sauvegardée"})
|
|
except Exception as e:
|
|
return jsonify({"success": False, "error": str(e)}), 500
|
|
|
|
|
|
# ==================== API Applications ====================
|
|
|
|
@app.route('/api/apps')
|
|
def api_apps_list():
|
|
"""Liste des applications configurées"""
|
|
config = load_config()
|
|
return jsonify(config.get('apps', []))
|
|
|
|
|
|
@app.route('/api/apps/launch/<int:app_id>', methods=['POST'])
|
|
def api_apps_launch(app_id):
|
|
"""Lance une application"""
|
|
config = load_config()
|
|
apps = config.get('apps', [])
|
|
|
|
if app_id < 0 or app_id >= len(apps):
|
|
return jsonify({"success": False, "error": "Application non trouvée"}), 404
|
|
|
|
app_config = apps[app_id]
|
|
|
|
try:
|
|
subprocess.Popen(app_config['path'], shell=True)
|
|
return jsonify({"success": True, "message": f"{app_config['name']} lancée"})
|
|
except Exception as e:
|
|
return jsonify({"success": False, "error": str(e)}), 500
|
|
|
|
|
|
# ==================== API Plexamp ====================
|
|
|
|
def init_plexamp():
|
|
"""Initialise le plugin Plexamp si configuré"""
|
|
global plexamp_plugin
|
|
|
|
config = load_config()
|
|
plexamp_config = config.get('media', {}).get('plexamp', {})
|
|
|
|
if plexamp_config.get('enabled') and plexamp_config.get('token'):
|
|
try:
|
|
plexamp_plugin = get_media_plugin('plexamp', plexamp_config)
|
|
print(f"Plexamp initialisé sur {plexamp_config.get('host')}:{plexamp_config.get('port')}")
|
|
except Exception as e:
|
|
print(f"Erreur initialisation Plexamp: {e}")
|
|
plexamp_plugin = None
|
|
else:
|
|
plexamp_plugin = None
|
|
|
|
|
|
@app.route('/api/plexamp/status')
|
|
def api_plexamp_status():
|
|
"""Retourne l'état actuel de lecture Plexamp"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"enabled": False, "error": "Plexamp non configuré"})
|
|
|
|
now_playing = plexamp_plugin.get_now_playing()
|
|
|
|
if not now_playing:
|
|
return jsonify({"enabled": True, "playing": False, "state": "unknown"})
|
|
|
|
# Ajouter l'URL complète de l'artwork
|
|
if now_playing.get('thumb'):
|
|
now_playing['artwork_url'] = plexamp_plugin.get_artwork_url(now_playing['thumb'])
|
|
|
|
now_playing['enabled'] = True
|
|
return jsonify(now_playing)
|
|
|
|
|
|
@app.route('/api/plexamp/play', methods=['POST'])
|
|
def api_plexamp_play():
|
|
"""Reprend la lecture"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
success = plexamp_plugin.play()
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/pause', methods=['POST'])
|
|
def api_plexamp_pause():
|
|
"""Met en pause"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
success = plexamp_plugin.pause()
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/playpause', methods=['POST'])
|
|
def api_plexamp_playpause():
|
|
"""Toggle play/pause"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
success = plexamp_plugin.play_pause()
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/next', methods=['POST'])
|
|
def api_plexamp_next():
|
|
"""Piste suivante"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
success = plexamp_plugin.next_track()
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/prev', methods=['POST'])
|
|
def api_plexamp_prev():
|
|
"""Piste précédente"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
success = plexamp_plugin.prev_track()
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/seek', methods=['POST'])
|
|
def api_plexamp_seek():
|
|
"""Aller à une position"""
|
|
global plexamp_plugin
|
|
|
|
if not plexamp_plugin:
|
|
return jsonify({"success": False, "error": "Plexamp non configuré"}), 400
|
|
|
|
data = request.get_json()
|
|
position = data.get('position', 0)
|
|
|
|
success = plexamp_plugin.seek(int(position))
|
|
return jsonify({"success": success})
|
|
|
|
|
|
@app.route('/api/plexamp/config', methods=['GET'])
|
|
def api_plexamp_config_get():
|
|
"""Récupère la config Plexamp"""
|
|
config = load_config()
|
|
plexamp_config = config.get('media', {}).get('plexamp', {})
|
|
# Ne pas renvoyer le token complet pour la sécurité
|
|
safe_config = {
|
|
'enabled': plexamp_config.get('enabled', False),
|
|
'host': plexamp_config.get('host', '127.0.0.1'),
|
|
'port': plexamp_config.get('port', 32400),
|
|
'has_token': bool(plexamp_config.get('token'))
|
|
}
|
|
return jsonify(safe_config)
|
|
|
|
|
|
@app.route('/api/plexamp/config', methods=['POST'])
|
|
def api_plexamp_config_save():
|
|
"""Sauvegarde la config Plexamp"""
|
|
global plexamp_plugin
|
|
|
|
data = request.get_json()
|
|
config = load_config()
|
|
|
|
if 'media' not in config:
|
|
config['media'] = {}
|
|
|
|
config['media']['plexamp'] = {
|
|
'enabled': data.get('enabled', False),
|
|
'host': data.get('host', '127.0.0.1'),
|
|
'port': data.get('port', 32400),
|
|
'token': data.get('token', '')
|
|
}
|
|
|
|
save_config(config)
|
|
|
|
# Réinitialiser le plugin
|
|
init_plexamp()
|
|
|
|
return jsonify({"success": True, "message": "Configuration Plexamp sauvegardée"})
|
|
|
|
|
|
@app.route('/api/plexamp/test', methods=['POST'])
|
|
def api_plexamp_test():
|
|
"""Teste la connexion Plexamp"""
|
|
data = request.get_json()
|
|
|
|
try:
|
|
test_plugin = get_media_plugin('plexamp', data)
|
|
result = test_plugin.test_connection()
|
|
return jsonify(result)
|
|
except Exception as e:
|
|
return jsonify({"success": False, "error": str(e)})
|
|
|
|
|
|
# ==================== Démarrage ====================
|
|
|
|
if __name__ == '__main__':
|
|
# Initialiser les plugins
|
|
init_plugin()
|
|
init_plexamp()
|
|
|
|
# Démarrer le thread d'historique
|
|
history_thread = Thread(target=update_history_loop, daemon=True)
|
|
history_thread.start()
|
|
|
|
config = load_config()
|
|
plugin_id = config.get('active_plugin', 'librehardwaremonitor')
|
|
plugin_config = config.get('plugins', {}).get(plugin_id, {})
|
|
plexamp_config = config.get('media', {}).get('plexamp', {})
|
|
|
|
print("=" * 60)
|
|
print("PC Monitor - Serveur de monitoring v1.2.2")
|
|
print("=" * 60)
|
|
print(f"Plugin actif: {plugin_id}")
|
|
print(f"Hôte: {plugin_config.get('host', '127.0.0.1')}")
|
|
print(f"Port: {plugin_config.get('port', 'N/A')}")
|
|
print("-" * 60)
|
|
if plexamp_config.get('enabled'):
|
|
print(f"Plexamp: activé ({plexamp_config.get('host')}:{plexamp_config.get('port')})")
|
|
else:
|
|
print("Plexamp: désactivé")
|
|
print("-" * 60)
|
|
print(f"Admin: http://localhost:5000/admin")
|
|
print(f"Dashboard: http://localhost:5000/dashboard")
|
|
print("=" * 60)
|
|
|
|
app.run(host='0.0.0.0', port=5000, debug=True)
|