diff --git a/README.html b/README.html
new file mode 100644
index 0000000..17cc961
--- /dev/null
+++ b/README.html
@@ -0,0 +1,201 @@
+
+
+
+
+ Aorus
+
+
+
+
+
+
+
+
+
+
+
+
+ Aorus
+Description
+installe un service qui creer des entites pour home assistant:
+
+- etat de la batterie
+- button pour eteindre le pc
+
+Prérequis
+installation de python3 et de python-env:
+sudo apt install python3-venv
+
+python3 -m venv monenv
+
+activation de l'environnement:
+source monenv/bin/activate
+
+Installation
+git clone http://10.0.1.200/pilot/aorus.git
+
+cd aorus
+
+Création de l'environnement:
+python3 -m venv monenv
+
+Activation de l'environnement:
+source monenv/bin/activate
+
+Installation des paquets additionnels:
+pip install -r requirements.txt
+
+Test du programme
+python3 main.py
+
+Sortie de l'environnement:
+deactivate
+
+Installation en temps que service
+authorisation de shutdown:
+sudo visudo
+
+gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
+
+Installation du service:
+sudo cp mqtt_pilot.service /etc/systemd/system/
+
+sudo systemctl daemon-reload
+
+sudo systemctl enable mqtt_pilot.service
+
+sudo systemctl start mqtt_pilot.service
+
+sudo systemctl status mqtt_pilot.service
+
+lancer l'installation du service:
+sudo ./install.sh
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 39dd721..5f3caaa 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,12 @@
installe un service qui creer des entites pour home assistant:
- etat de la batterie
- button pour eteindre le pc
+- reboot
+- eteindre l'ecran
+- cpu
+- memory
+- adresse ip
+- cpu frequency
## Prérequis
@@ -56,15 +62,17 @@ deactivate
## Installation en temps que service
-authorisation de shutdown:
+authorisation de shutdown: ajouter a la fin du fichier
```
sudo visudo
```
```
gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
+gilles ALL=(ALL) NOPASSWD: /sbin/reboot
+gilles ALL=(ALL) NOPASSWD: /usr/bin/tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
```
-Installation du service:
+Installation du service en manuel:
```
sudo cp mqtt_pilot.service /etc/systemd/system/
@@ -81,3 +89,7 @@ sudo systemctl start mqtt_pilot.service
```
sudo systemctl status mqtt_pilot.service
```
+lancer l'installation du service:
+```
+sudo ./install.sh
+```
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..68b36e8
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# Vérifier si le script est exécuté avec les privilèges root
+if [ "$EUID" -ne 0 ]; then
+ echo "Veuillez exécuter ce script avec sudo ou en tant que root."
+ exit 1
+fi
+
+# Copier le fichier de service dans le répertoire systemd
+cp mqtt_pilot.service /etc/systemd/system/
+
+# Recharger systemd pour prendre en compte le nouveau service
+systemctl daemon-reload
+
+# Activer le service pour qu'il démarre au démarrage
+systemctl enable mqtt_pilot.service
+
+# Démarrer le service immédiatement
+systemctl stop mqtt_pilot.service
+systemctl start mqtt_pilot.service
+
+echo "Le service mqtt_pilot a été installé et démarré avec succès."
\ No newline at end of file
diff --git a/main_prog.py b/main_prog.py
new file mode 100644
index 0000000..35063a1
--- /dev/null
+++ b/main_prog.py
@@ -0,0 +1,535 @@
+# ajouter cette ligne en bas du fichier : sudo visudo
+# gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
+# gilles ALL=(ALL) NOPASSWD: /sbin/reboot
+# gilles ALL=(ALL) NOPASSWD: /usr/bin/tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
+
+
+# structure du message discovery //[/]/config
+
+import os
+import time
+import json
+import paho.mqtt.client as mqtt
+import subprocess
+import threading
+import psutil
+import threading
+
+stop_threads = threading.Event()
+
+# Paramètres MQTT
+mqtt_broker_ip_address = "10.0.0.3"
+mqtt_port = 1883
+mqtt_username = ""
+mqtt_password = ""
+default_update_frequency = 60 # Mise à jour toutes les 60 secondes
+discovery_prefix = "homeassistant"
+device_name = "yoga14"
+mac_address = "60:57:18:99:ed:05"
+node_id = device_name
+mise_a_jours_frequente = 5
+mise_a_jour_moyenne = 30
+mise_a_jour_lente = 60
+
+device_info = {
+ "identifiers": [device_name],
+ "name": "Yoga 14",
+ "manufacturer": "Lenovo",
+ "model": "laptop",
+ "sw_version": "1.0.0",
+ "suggested_area": "salon",
+}
+
+
+# Configuration des entités
+shutdown_entity = {
+ "name": f"shutdown_{device_name}",
+ "type": "switch",
+ "unique_id": f"shutdown_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/shutdown/set",
+ "state_topic": f"pilot/{device_name}/shutdown/state",
+ "availability_topic": f"pilot/{device_name}/shutdown/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:power",
+ "device": device_info,
+
+
+}
+reboot_entity = {
+ "name": f"reboot_{device_name}",
+ "type": "switch",
+ "unique_id": f"reboot_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/reboot/set",
+ "state_topic": f"pilot/{device_name}/reboot/state",
+ "availability_topic": f"pilot/{device_name}/reboot/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:restart",
+ "device": device_info,
+}
+
+battery_entity = {
+ "name": f"battery_{device_name}",
+ "type": "sensor",
+ "unique_id": f"battery_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/battery/state",
+ "unit_of_measurement": "%",
+ "device_class": "battery",
+ "availability_topic": f"pilot/{device_name}/battery/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:battery",
+ "device": device_info,
+ "update_interval": 60
+
+}
+
+charging_status_entity = {
+ "name": f"charging_status_{device_name}",
+ "type": "binary_sensor",
+ "unique_id": f"charging_status_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/charging_status/state",
+ "availability_topic": f"pilot/{device_name}/charging_status/available",
+ "device_class": "battery_charging",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:battery-charging",
+ "device": device_info,
+ "update_interval": 5
+}
+
+screen_entity = {
+ "name": f"screen_{device_name}",
+ "type": "switch",
+ "unique_id": f"screen_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/screen/set",
+ "state_topic": f"pilot/{device_name}/screen/state",
+ "availability_topic": f"pilot/{device_name}/screen/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:monitor",
+ "device": device_info,
+}
+
+# Ajout des nouvelles entités pour le CPU et la mémoire
+cpu_temperature_entity = {
+ "name": f"cpu_temperature_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_temperature_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_temperature/state",
+ "unit_of_measurement": "°C",
+ "device_class": "temperature",
+ "availability_topic": f"pilot/{device_name}/cpu_temperature/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:thermometer",
+ "device": device_info,
+ "update_interval": 20
+}
+
+cpu_usage_entity = {
+ "name": f"cpu_usage_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_usage_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_usage/state",
+ "unit_of_measurement": "%",
+ "device_class": "power",
+ "availability_topic": f"pilot/{device_name}/cpu_usage/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:chip",
+ "device": device_info,
+ "update_interval": 10
+}
+
+memory_usage_entity = {
+ "name": f"memory_usage_{device_name}",
+ "type": "sensor",
+ "unique_id": f"memory_usage_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/memory_usage/state",
+ "unit_of_measurement": "%",
+ # "device_class": "memory",
+ "availability_topic": f"pilot/{device_name}/memory_usage/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:memory",
+ "device": device_info,
+ "update_interval": 10
+}
+
+cpu_frequency_entity = {
+ "name": f"cpu_frequency_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_frequency_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_frequency/state",
+ "unit_of_measurement": "GHz",
+ "device_class": "frequency",
+ "availability_topic": f"pilot/{device_name}/cpu_frequency/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:speedometer",
+ "device": device_info,
+ "update_interval": 20
+}
+
+ip_address_entity = {
+ "name": f"ip_address_{device_name}",
+ "type": "sensor",
+ "unique_id": f"ip_address_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/ip_address/state",
+ "availability_topic": f"pilot/{device_name}/ip_address/available",
+ #"device_class": "connectivity",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:ip",
+ "device": device_info,
+ "update_interval": 60
+}
+
+cpu_frequency_slider_entity = {
+ "name": f"cpu_frequency_slider_{device_name}",
+ "type": "number",
+ "unique_id": f"cpu_frequency_slider_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/cpu_frequency_slider/set",
+ "state_topic": f"pilot/{device_name}/cpu_frequency_slider/state",
+ "availability_topic": f"pilot/{device_name}/cpu_frequency_slider/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "min": 0.5,
+ "max": 3.0,
+ "step": 0.1,
+ "unit_of_measurement": "GHz",
+ "icon": "mdi:speedometer",
+ "device": device_info,
+}
+
+def publish_discovery_messages(client):
+ # Publie les messages de découverte pour les entités
+ # ...
+ # print("publish_discovery_messages")
+ client.publish(f"{discovery_prefix}/switch/{node_id}/{shutdown_entity['name']}/config", json.dumps(shutdown_entity), retain=True)
+ client.publish(f"{discovery_prefix}/switch/{node_id}/{reboot_entity['name']}/config", json.dumps(reboot_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{battery_entity['name']}/config", json.dumps(battery_entity), retain=True)
+ client.publish(f"{discovery_prefix}/switch/{node_id}/{screen_entity['name']}/config", json.dumps(screen_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{cpu_temperature_entity['name']}/config", json.dumps(cpu_temperature_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{cpu_usage_entity['name']}/config", json.dumps(cpu_usage_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{memory_usage_entity['name']}/config", json.dumps(memory_usage_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{cpu_frequency_entity['name']}/config", json.dumps(cpu_frequency_entity), retain=True)
+ client.publish(f"{discovery_prefix}/binary_sensor/{node_id}/{charging_status_entity['name']}/config", json.dumps(charging_status_entity), retain=True)
+ client.publish(f"{discovery_prefix}/sensor/{node_id}/{ip_address_entity['name']}/config", json.dumps(ip_address_entity), retain=True)
+ client.publish(f"{discovery_prefix}/number/{node_id}/{cpu_frequency_slider_entity['name']}/config", json.dumps(cpu_frequency_slider_entity), retain=True)
+
+
+
+ # print("Discovery messages published")
+
+def publish_availability(client):
+ client.publish(shutdown_entity["availability_topic"], shutdown_entity["payload_available"], retain=True)
+ client.publish(reboot_entity["availability_topic"], reboot_entity["payload_available"], retain=True)
+ client.publish(battery_entity["availability_topic"], battery_entity["payload_available"], retain=True)
+ client.publish(screen_entity["availability_topic"], screen_entity["payload_available"], retain=True)
+ client.publish(cpu_temperature_entity["availability_topic"], cpu_temperature_entity["payload_available"], retain=True)
+ client.publish(cpu_usage_entity["availability_topic"], cpu_usage_entity["payload_available"], retain=True)
+ client.publish(memory_usage_entity["availability_topic"], memory_usage_entity["payload_available"], retain=True)
+ client.publish(cpu_frequency_entity["availability_topic"], cpu_frequency_entity["payload_available"], retain=True)
+ client.publish(charging_status_entity["availability_topic"], charging_status_entity["payload_available"], retain=True)
+ client.publish(ip_address_entity["availability_topic"], ip_address_entity["payload_available"], retain=True)
+ client.publish(cpu_frequency_slider_entity["availability_topic"], cpu_frequency_slider_entity["payload_available"], retain=True)
+ # print("Published availability for all entities")
+
+def get_local_ip_address():
+ try:
+ import socket
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.settimeout(0)
+ s.connect(('10.254.254.254', 1)) # Adresse IP arbitraire pour établir une connexion
+ local_ip = s.getsockname()[0]
+ s.close()
+ print(f"Publishing IP address: {local_ip}") # Log l'adresse IP
+ return local_ip
+ except Exception as e:
+ print(f"Error retrieving local IP address: {e}")
+ return None
+
+
+def get_cpu_temperature():
+ # Utilisation de psutil ou autre pour obtenir la température du CPU
+ try:
+ temp = psutil.sensors_temperatures()['coretemp'][0].current # Par exemple pour les CPUs Intel
+ print(f"Publishing CPU temperature: {temp}°C")
+ return temp
+ except Exception as e:
+ print(f"Error reading CPU temperature: {e}")
+ return None
+
+def get_cpu_usage():
+ try:
+ cpu_percent = psutil.cpu_percent(interval=1)
+ print(f"CPU usage: {cpu_percent}%") # Ajoute ce log pour déboguer
+ return cpu_percent
+ except Exception as e:
+ print(f"Error reading CPU usage: {e}")
+ return None
+
+def get_memory_usage():
+ try:
+ memory_info = psutil.virtual_memory()
+ print(f"Memory usage: {memory_info.percent}%") # Ajoute ce log pour déboguer
+ return memory_info.percent
+ except Exception as e:
+ print(f"Error reading memory usage: {e}")
+ return None
+
+def get_cpu_frequency():
+ try:
+ with open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r") as file:
+ # La fréquence est en kHz, donc on la convertit en GHz
+ freq_khz = int(file.read().strip())
+ freq_ghz = freq_khz / 1_000_000 # Conversion de kHz à GHz
+ print(f"CPU frequency: {freq_ghz:.2f} GHz") # Ajoute ce log pour déboguer
+ return f"{freq_ghz:.2f}" # Formater avec 2 chiffres après la virgule
+ except Exception as e:
+ print(f"Error reading CPU frequency: {e}")
+ return None
+
+def get_battery_level():
+ try:
+ with open("/sys/class/power_supply/BAT0/capacity", "r") as file:
+ battery_level = file.read().strip()
+ print(f"Publishing battery level: {battery_level}%")
+ return battery_level
+ except Exception as e:
+ print(f"Error reading battery level: {e}")
+ return None
+
+def get_charging_status():
+ try:
+ with open("/sys/class/power_supply/ADP1/online", "r") as file:
+ status = file.read().strip()
+ print(f"Publishing charging status: {status}")
+ return "ON" if status == "1" else "OFF"
+ except Exception as e:
+ print(f"Error reading charging status: {e}")
+ return None
+
+def set_cpu_frequency(frequency):
+ try:
+ frequency_khz = int(float(frequency) * 1_000_000) # Convertir GHz en kHz
+ with open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", "w") as file:
+ file.write(str(frequency_khz))
+ print(f"Set CPU frequency to {frequency} GHz")
+ except Exception as e:
+ print(f"Error setting CPU frequency: {e}")
+
+
+def publish_sensor_data(client):
+ battery_level = get_battery_level()
+ if battery_level is not None:
+ client.publish(battery_entity["state_topic"], battery_level, retain=True)
+
+ cpu_temp = get_cpu_temperature()
+ if cpu_temp is not None:
+ client.publish(cpu_temperature_entity["state_topic"], cpu_temp, retain=True)
+
+ cpu_usage = get_cpu_usage()
+ if cpu_usage is not None:
+ client.publish(cpu_usage_entity["state_topic"], cpu_usage, retain=True)
+
+ memory_usage = get_memory_usage()
+ if memory_usage is not None:
+ print(f"Publishing memory usage: {memory_usage}%") # Ajoute ce log
+ client.publish(memory_usage_entity["state_topic"], memory_usage, retain=True)
+
+ cpu_freq = get_cpu_frequency()
+ if cpu_freq is not None:
+ client.publish(cpu_frequency_entity["state_topic"], cpu_freq, retain=True)
+ print(f"Published CPU frequency: {cpu_freq} GHz")
+
+ charging_status = get_charging_status()
+ if charging_status is not None:
+ client.publish(charging_status_entity["state_topic"], charging_status, retain=True)
+
+ threading.Timer(update_frequency, publish_sensor_data, [client]).start()
+
+def publish_battery_level(client):
+ battery_level = get_battery_level()
+ if battery_level is not None:
+ client.publish(battery_entity["state_topic"], battery_level, retain=True)
+ threading.Timer(get_update_interval(battery_entity), publish_battery_level, [client]).start()
+
+def publish_cpu_temperature(client):
+ cpu_temp = get_cpu_temperature()
+ if cpu_temp is not None:
+ client.publish(cpu_temperature_entity["state_topic"], cpu_temp, retain=True)
+ threading.Timer(get_update_interval(cpu_temperature_entity), publish_cpu_temperature, [client]).start()
+
+def publish_cpu_usage(client):
+ cpu_usage = get_cpu_usage()
+ if cpu_usage is not None:
+ client.publish(cpu_usage_entity["state_topic"], cpu_usage, retain=True)
+ threading.Timer(get_update_interval(cpu_usage_entity), publish_cpu_usage, [client]).start()
+
+def publish_memory_usage(client):
+ memory_usage = get_memory_usage()
+ if memory_usage is not None:
+ client.publish(memory_usage_entity["state_topic"], memory_usage, retain=True)
+ threading.Timer(get_update_interval(memory_usage_entity), publish_memory_usage, [client]).start()
+
+def publish_cpu_frequency(client):
+ cpu_freq = get_cpu_frequency()
+ if cpu_freq is not None:
+ client.publish(cpu_frequency_entity["state_topic"], cpu_freq, retain=True)
+ threading.Timer(get_update_interval(cpu_frequency_entity), publish_cpu_frequency, [client]).start()
+
+def publish_charging_status(client):
+ charging_status = get_charging_status()
+ if charging_status is not None:
+ client.publish(charging_status_entity["state_topic"], charging_status, retain=True)
+ threading.Timer(get_update_interval(charging_status_entity), publish_charging_status, [client]).start()
+
+def publish_ip_address(client):
+ local_ip = get_local_ip_address()
+ if local_ip is not None:
+ client.publish(ip_address_entity["state_topic"], local_ip, retain=True)
+ threading.Timer(get_update_interval(ip_address_entity), publish_ip_address, [client]).start()
+
+def publish_current_cpu_frequency(client):
+ cpu_freq = get_cpu_frequency()
+ if cpu_freq is not None:
+ client.publish(cpu_frequency_slider_entity["state_topic"], cpu_freq, retain=True)
+
+def get_update_interval(entity):
+ return entity.get("update_interval", default_update_frequency)
+
+
+def on_connect(client, userdata, flags, rc):
+ if rc == 0:
+ print("Connected with result code {rc}")
+ client.subscribe(shutdown_entity["command_topic"])
+ client.subscribe(reboot_entity["command_topic"])
+ client.subscribe(screen_entity["command_topic"])
+ client.subscribe(cpu_frequency_slider_entity["command_topic"]) # S'abonner au slider
+ publish_discovery_messages(client)
+ publish_availability(client)
+
+ # Démarrer la publication des données avec les fréquences respectives
+ publish_battery_level(client)
+ publish_cpu_temperature(client)
+ publish_cpu_usage(client)
+ publish_memory_usage(client)
+ publish_cpu_frequency(client)
+ publish_charging_status(client)
+ publish_ip_address(client) # Ajout de la publication de l'adresse IP
+ publish_current_cpu_frequency(client) # Publier l'état initial du slider
+
+
+ # Publier l'état "ON" pour le switch au démarrage
+ client.publish(shutdown_entity["state_topic"], shutdown_entity["payload_on"], retain=True)
+ client.publish(reboot_entity["state_topic"], reboot_entity["payload_on"], retain=True)
+ client.publish(screen_entity["state_topic"], screen_entity["payload_on"], retain=True)
+ print(f"Set {shutdown_entity['name']} to ON")
+
+def deactivate_entities(client):
+ """Désactive toutes les entités en les marquant comme 'unavailable'."""
+ client.publish(shutdown_entity["availability_topic"], shutdown_entity["payload_not_available"], retain=True)
+ client.publish(reboot_entity["availability_topic"], reboot_entity["payload_not_available"], retain=True)
+ client.publish(battery_entity["availability_topic"], battery_entity["payload_not_available"], retain=True)
+ client.publish(screen_entity["availability_topic"], screen_entity["payload_not_available"], retain=True)
+ client.publish(cpu_temperature_entity["availability_topic"], cpu_temperature_entity["payload_not_available"], retain=True)
+ client.publish(cpu_usage_entity["availability_topic"], cpu_usage_entity["payload_not_available"], retain=True)
+ client.publish(memory_usage_entity["availability_topic"], memory_usage_entity["payload_not_available"], retain=True)
+ client.publish(cpu_frequency_entity["availability_topic"], cpu_frequency_entity["payload_not_available"], retain=True)
+ client.publish(charging_status_entity["availability_topic"], charging_status_entity["payload_not_available"], retain=True)
+ client.publish(ip_address_entity["availability_topic"], ip_address_entity["payload_not_available"], retain=True)
+ client.publish(cpu_frequency_slider_entity["availability_topic"], cpu_frequency_slider_entity["payload_not_available"], retain=True)
+ client.loop_stop() # Arrête la boucle MQTT proprement pour s'assurer que tous les messages sont publiés
+ print("All entities deactivated.")
+
+
+def on_message(client, userdata, message):
+ # Gestion des messages MQTT
+ print("on_message")
+ # Vérifier si le message est pour le switch "shutdown"
+ if message.topic == shutdown_entity["command_topic"]:
+ if message.payload.decode() == shutdown_entity["payload_off"]:
+ print("Received 'OFF' command - shutting down the system")
+ client.publish(shutdown_entity["state_topic"], shutdown_entity["payload_off"], retain=True)
+ # Exécuter la commande de shutdown
+ time.sleep(1)
+ deactivate_entities(client) # Désactiver toutes les entités avant de fermer
+ time.sleep(2)
+ subprocess.run(["sudo", "shutdown", "-h", "now"])
+ exit(0) # Sortir immédiatement du programme après le shutdown
+ elif message.payload.decode() == shutdown_entity["payload_on"]:
+ print("Received 'ON' command - no action for 'ON'")
+
+ elif message.topic == reboot_entity["command_topic"]:
+ if message.payload.decode() == reboot_entity["payload_off"]:
+ print("Received 'OFF' command - rebooting the system")
+ client.publish(reboot_entity["state_topic"], reboot_entity["payload_off"], retain=True)
+ time.sleep(1)
+ deactivate_entities(client) # Désactiver toutes les entités avant de redémarrer
+ subprocess.run(["sudo", "reboot"])
+ os._exit(0) # Sortir immédiatement du programme après le reboot
+ elif message.payload.decode() == reboot_entity["payload_on"]:
+ print("Received 'ON' command - no action for 'ON'")
+
+ elif message.topic == screen_entity["command_topic"]:
+ if message.payload.decode() == screen_entity["payload_off"]:
+ print("Received 'OFF' command - turning off the screen")
+ client.publish(screen_entity["state_topic"], screen_entity["payload_off"], retain=True)
+ result = subprocess.run(["busctl", "--user", "set-property", "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig", "org.gnome.Mutter.DisplayConfig", "PowerSaveMode", "i", "1"], capture_output=True, text=True)
+ print(f"Command output: {result.stdout}")
+ if result.stderr:
+ print(f"Command error: {result.stderr}")
+ elif message.payload.decode() == screen_entity["payload_on"]:
+ print("Received 'ON' command - turning on the screen")
+ client.publish(screen_entity["state_topic"], screen_entity["payload_on"], retain=True)
+ result = subprocess.run(["busctl", "--user", "set-property", "org.gnome.Mutter.DisplayConfig", "/org/gnome/Mutter/DisplayConfig", "org.gnome.Mutter.DisplayConfig", "PowerSaveMode", "i", "0"], capture_output=True, text=True)
+ print(f"Command output: {result.stdout}")
+ if result.stderr:
+ print(f"Command error: {result.stderr}")
+
+ elif message.topic == cpu_frequency_slider_entity["command_topic"]:
+ frequency = message.payload.decode()
+ print(f"Received CPU frequency slider command: {frequency} GHz")
+ set_cpu_frequency(frequency)
+ client.publish(cpu_frequency_entity["state_topic"], frequency, retain=True)
+ client.publish(cpu_frequency_slider_entity["state_topic"], frequency, retain=True)
+
+
+
+
+# Configuration et démarrage du client MQTT
+client = mqtt.Client()
+client.username_pw_set(mqtt_username, mqtt_password)
+client.on_connect = on_connect
+client.on_message = on_message
+client.connect(mqtt_broker_ip_address, mqtt_port, 60)
+client.loop_start()
+
+# Maintenir le script en exécution
+try:
+ while True:
+ publish_availability(client) # Maintenir l'état disponible
+ time.sleep(1) # Attendre avant la prochaine mise à jour
+except KeyboardInterrupt:
+ print("Script interrupted, closing MQTT connection")
+ # Publier l'état "unavailable" pour les entités
+ deactivate_entities(client)
+ time.sleep(1)
+
+ # Fermer la connexion MQTT proprement
+ client.disconnect()
diff --git a/mqtt_pilot.service b/mqtt_pilot.service
index 86fd11a..be3d65b 100644
--- a/mqtt_pilot.service
+++ b/mqtt_pilot.service
@@ -8,10 +8,12 @@ After=network-online.target
Type=simple
User=gilles
# Délai avant de démarrer le service
-ExecStartPre=/bin/sleep 60
-ExecStart=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/main.py
+ExecStartPre=/bin/sleep 30
+ExecStart=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/main_prog.py
Restart=on-failure
RestartSec=30
ExecStopPost=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/mqtt_unvai.py
+StandardOutput=journal
+StandardError=journal
[Install]
WantedBy=multi-user.target
diff --git a/mqtt_unvai.py b/mqtt_unvai.py
index a7c5343..351c8cc 100644
--- a/mqtt_unvai.py
+++ b/mqtt_unvai.py
@@ -9,91 +9,226 @@ mqtt_port = 1883
mqtt_username = ""
mqtt_password = ""
+discovery_prefix = "homeassistant"
+device_name = "yoga14"
+mac_address = "60:57:18:99:ed:05" # Ajout du mac_address manquant
+
+device_info = {
+ "identifiers": [device_name],
+ "name": "Yoga 14",
+ "manufacturer": "Lenovo",
+ "model": "laptop",
+ "sw_version": "1.0.0",
+ "suggested_area": "salon",
+}
+
# Configuration des entités
shutdown_entity = {
- "availability_topic": f"pilot/{hostname}/shutdown/available",
+ "name": f"shutdown_{device_name}",
+ "type": "switch",
+ "unique_id": f"shutdown_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/shutdown/set",
+ "state_topic": f"pilot/{device_name}/shutdown/state",
+ "availability_topic": f"pilot/{device_name}/shutdown/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
"payload_not_available": "offline",
+ "icon": "mdi:power",
+ "device": device_info,
+
+
+}
+reboot_entity = {
+ "name": f"reboot_{device_name}",
+ "type": "switch",
+ "unique_id": f"reboot_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/reboot/set",
+ "state_topic": f"pilot/{device_name}/reboot/state",
+ "availability_topic": f"pilot/{device_name}/reboot/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:restart",
+ "device": device_info,
}
-# battery_entity = {
-# "availability_topic": f"pilot/{hostname}/battery/available",
-# "payload_not_available": "offline",
-# }
+battery_entity = {
+ "name": f"battery_{device_name}",
+ "type": "sensor",
+ "unique_id": f"battery_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/battery/state",
+ "unit_of_measurement": "%",
+ "device_class": "battery",
+ "availability_topic": f"pilot/{device_name}/battery/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:battery",
+ "device": device_info,
+ "update_interval": 60
+
+}
+
+charging_status_entity = {
+ "name": f"charging_status_{device_name}",
+ "type": "binary_sensor",
+ "unique_id": f"charging_status_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/charging_status/state",
+ "availability_topic": f"pilot/{device_name}/charging_status/available",
+ "device_class": "battery_charging",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:battery-charging",
+ "device": device_info,
+ "update_interval": 5
+}
+
+screen_entity = {
+ "name": f"screen_{device_name}",
+ "type": "switch",
+ "unique_id": f"screen_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/screen/set",
+ "state_topic": f"pilot/{device_name}/screen/state",
+ "availability_topic": f"pilot/{device_name}/screen/available",
+ "device_class": "switch",
+ "payload_on": "ON",
+ "payload_off": "OFF",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:monitor",
+ "device": device_info,
+}
+
+# Ajout des nouvelles entités pour le CPU et la mémoire
cpu_temperature_entity = {
- "availability_topic": f"pilot/{hostname}/cpu_temp/available",
+ "name": f"cpu_temperature_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_temperature_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_temperature/state",
+ "unit_of_measurement": "°C",
+ "device_class": "temperature",
+ "availability_topic": f"pilot/{device_name}/cpu_temperature/available",
+ "payload_available": "online",
"payload_not_available": "offline",
+ "icon": "mdi:thermometer",
+ "device": device_info,
+ "update_interval": 20
}
-gpu_temperature_entity = {
- "availability_topic": f"pilot/{hostname}/gpu_temp/available",
- "payload_not_available": "offline",
-}
-gpu_memory_entity = {
- "availability_topic": f"pilot/{hostname}/gpu_memory_usage/available",
+cpu_usage_entity = {
+ "name": f"cpu_usage_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_usage_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_usage/state",
+ "unit_of_measurement": "%",
+ "device_class": "power",
+ "availability_topic": f"pilot/{device_name}/cpu_usage/available",
+ "payload_available": "online",
"payload_not_available": "offline",
+ "icon": "mdi:chip",
+ "device": device_info,
+ "update_interval": 10
}
memory_usage_entity = {
- "availability_topic": f"pilot/{hostname}/memory_used/available",
- "payload_not_available": "offline",
-}
-cpu_usage_entity = {
- "availability_topic": f"pilot/{hostname}/cpu_usage/available",
+ "name": f"memory_usage_{device_name}",
+ "type": "sensor",
+ "unique_id": f"memory_usage_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/memory_usage/state",
+ "unit_of_measurement": "%",
+ # "device_class": "memory",
+ "availability_topic": f"pilot/{device_name}/memory_usage/available",
+ "payload_available": "online",
"payload_not_available": "offline",
+ "icon": "mdi:memory",
+ "device": device_info,
+ "update_interval": 10
}
-# Fonction pour publier l'état "unavailable" pour les entités
-def publish_unavailability(client):
- client.publish(
- shutdown_entity["availability_topic"],
- shutdown_entity["payload_not_available"],
- retain=True,
- )
- # client.publish(
- # battery_entity["availability_topic"],
- # battery_entity["payload_not_available"],
- # retain=True,
- # )
+cpu_frequency_entity = {
+ "name": f"cpu_frequency_{device_name}",
+ "type": "sensor",
+ "unique_id": f"cpu_frequency_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/cpu_frequency/state",
+ "unit_of_measurement": "GHz",
+ "device_class": "frequency",
+ "availability_topic": f"pilot/{device_name}/cpu_frequency/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:speedometer",
+ "device": device_info,
+ "update_interval": 20
+}
- client.publish(
- cpu_temperature_entity["availability_topic"],
- cpu_temperature_entity["payload_not_available"],
- retain=True,
- )
- client.publish(
- gpu_temperature_entity["availability_topic"],
- gpu_temperature_entity["payload_not_available"],
- retain=True,
- )
- client.publish(
- gpu_memory_entity["availability_topic"],
- gpu_memory_entity["payload_not_available"],
- retain=True,
- )
- client.publish(
- cpu_usage_entity["availability_topic"],
- cpu_usage_entity["payload_not_available"],
- retain=True,
- )
- client.publish(
- memory_usage_entity["availability_topic"],
- memory_usage_entity["payload_not_available"],
- retain=True,
- )
- print("Published unavailability for all entities")
+ip_address_entity = {
+ "name": f"ip_address_{device_name}",
+ "type": "sensor",
+ "unique_id": f"ip_address_{device_name}_{mac_address}",
+ "state_topic": f"pilot/{device_name}/ip_address/state",
+ "availability_topic": f"pilot/{device_name}/ip_address/available",
+ #"device_class": "connectivity",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "icon": "mdi:ip",
+ "device": device_info,
+ "update_interval": 60
+}
+
+cpu_frequency_slider_entity = {
+ "name": f"cpu_frequency_slider_{device_name}",
+ "type": "number",
+ "unique_id": f"cpu_frequency_slider_{device_name}_{mac_address}",
+ "command_topic": f"pilot/{device_name}/cpu_frequency_slider/set",
+ "state_topic": f"pilot/{device_name}/cpu_frequency_slider/state",
+ "availability_topic": f"pilot/{device_name}/cpu_frequency_slider/available",
+ "payload_available": "online",
+ "payload_not_available": "offline",
+ "min": 0.5,
+ "max": 3.0,
+ "step": 0.1,
+ "unit_of_measurement": "GHz",
+ "icon": "mdi:speedometer",
+ "device": device_info,
+}
+
+def deactivate_entities(client):
+ """Désactive toutes les entités en les marquant comme 'unavailable'."""
+ entities = [
+ shutdown_entity,
+ reboot_entity,
+ battery_entity,
+ screen_entity,
+ cpu_temperature_entity,
+ cpu_usage_entity,
+ memory_usage_entity,
+ cpu_frequency_entity,
+ charging_status_entity,
+ ip_address_entity,
+ cpu_frequency_slider_entity
+ ]
+
+ for entity in entities:
+ client.publish(entity["availability_topic"], entity["payload_not_available"], retain=True)
+
+ client.loop_stop() # Arrête la boucle MQTT proprement pour s'assurer que tous les messages sont publiés
+ print("All entities deactivated.")
# Fonction appelée lors de la connexion au broker MQTT
def on_connect(client, userdata, flags, rc):
if rc == 0:
- print("Connected with result code {rc}")
- publish_unavailability(client)
+ print(f"Connected with result code {rc}")
+ deactivate_entities(client)
client.disconnect() # Déconnecter après la publication
-
# Configuration et démarrage du client MQTT
client = mqtt.Client()
client.username_pw_set(mqtt_username, mqtt_password)
client.on_connect = on_connect
client.connect(mqtt_broker_ip_address, mqtt_port, 60)
-client.loop_forever()
+client.loop_forever()
\ No newline at end of file