premier envoie
This commit is contained in:
400
main.py
Normal file
400
main.py
Normal file
@@ -0,0 +1,400 @@
|
||||
# ajouter cette ligne en bas du fichier : sudo visudo
|
||||
# gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
|
||||
|
||||
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import paho.mqtt.client as mqtt
|
||||
import subprocess
|
||||
import threading
|
||||
import psutil
|
||||
import pynvml
|
||||
|
||||
# Initialisation de pynvml
|
||||
pynvml.nvmlInit()
|
||||
|
||||
# Fonctions pour obtenir les températures CPU et GPU
|
||||
def get_cpu_temperature():
|
||||
temps = psutil.sensors_temperatures()
|
||||
for name, entries in temps.items():
|
||||
if name == 'k10temp':
|
||||
for entry in entries:
|
||||
if entry.label == 'Tctl':
|
||||
return entry.current
|
||||
|
||||
def get_gpu_temperature():
|
||||
try:
|
||||
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
|
||||
return pynvml.nvmlDeviceGetTemperature(handle, pynvml.NVML_TEMPERATURE_GPU)
|
||||
except pynvml.NVMLError as error:
|
||||
print(f"Failed to get GPU temperature: {error}")
|
||||
return None
|
||||
|
||||
def get_gpu_memory_usage():
|
||||
pynvml.nvmlInit()
|
||||
handle = pynvml.nvmlDeviceGetHandleByIndex(0) # 0 pour la première carte graphique
|
||||
info = pynvml.nvmlDeviceGetMemoryInfo(handle)
|
||||
pynvml.nvmlShutdown()
|
||||
|
||||
memory_used_gb = info.used / 1024 / 1024 # Convertir en GB
|
||||
return round(memory_used_gb, 2) # Arrondir à 2 chiffres après la virgule
|
||||
|
||||
# Paramètres MQTT
|
||||
mqtt_broker_ip_address = "10.0.0.3"
|
||||
mqtt_port = 1883
|
||||
mqtt_username = ""
|
||||
mqtt_password = ""
|
||||
#update_frequency = 60 # Mise à jour toutes les 60 secondes
|
||||
discovery_prefix = "homeassistant"
|
||||
update_frequency = 5 # en secondes
|
||||
|
||||
# Fonction pour obtenir la quantité de mémoire utilisée
|
||||
def get_memory_used():
|
||||
memory_info = psutil.virtual_memory()
|
||||
memory_used_mb = memory_info.used / 1024 / 1024 # Convertir en MB
|
||||
return round(memory_used_mb) # Arrondir à 0 chiffre après la virgule
|
||||
|
||||
def get_cpu_usage():
|
||||
cpu_usage = psutil.cpu_percent()
|
||||
return round(cpu_usage, 1) # Arrondir à 1 chiffre après la virgule
|
||||
|
||||
|
||||
device_info = {
|
||||
"identifiers": ["aorus"],
|
||||
"name": "Aorus",
|
||||
"manufacturer": "GigaByte",
|
||||
"model": "desktop",
|
||||
"sw_version": "1.0.0",
|
||||
"suggested_area": "salon",
|
||||
}
|
||||
|
||||
|
||||
# Configuration des entités
|
||||
shutdown_entity = {
|
||||
"name": "shutdown_aorus",
|
||||
"type": "switch",
|
||||
"unique_id": "shutdown_aorus_18:c0:4d:b5:65:74",
|
||||
"command_topic": "pilot/aorus/shutdown/set",
|
||||
"state_topic": "pilot/aorus/shutdown",
|
||||
"availability_topic": "pilot/aorus/shutdown/available",
|
||||
"device_class": "switch",
|
||||
"payload_on": "ON",
|
||||
"payload_off": "OFF",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:power",
|
||||
"device": device_info,
|
||||
}
|
||||
|
||||
# battery_entity = {
|
||||
# "name": "battery_aorus",
|
||||
# "type": "sensor",
|
||||
# "unique_id": "battery_aorus_18:c0:4d:b5:65:74",
|
||||
# "state_topic": "pilot/aorus/battery",
|
||||
# "unit_of_measurement": "%",
|
||||
# "device_class": "battery",
|
||||
# "availability_topic": "pilot/aorus/battery/available",
|
||||
# "payload_available": "online",
|
||||
# "payload_not_available": "offline",
|
||||
# "icon": "mdi:battery",
|
||||
# "device": device_info,
|
||||
# }
|
||||
|
||||
cpu_temp_entity = {
|
||||
"name": "cpu_temp_aorus",
|
||||
"type": "sensor",
|
||||
"unique_id": "cpu_temp_aorus_18:c0:4d:b5:65:74",
|
||||
"state_topic": "pilot/aorus/cpu_temp",
|
||||
"availability_topic": "pilot/aorus/cpu_temp/available",
|
||||
"device_class": "temperature",
|
||||
"unit_of_measurement": "°C",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:thermometer",
|
||||
"device": device_info,
|
||||
}
|
||||
|
||||
gpu_temp_entity = {
|
||||
"name": "gpu_temp_aorus",
|
||||
"type": "sensor",
|
||||
"unique_id": "gpu_temp_aorus_18:c0:4d:b5:65:74",
|
||||
"state_topic": "pilot/aorus/gpu_temp",
|
||||
"availability_topic": "pilot/aorus/gpu_temp/available",
|
||||
"device_class": "temperature",
|
||||
"unit_of_measurement": "°C",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:thermometer",
|
||||
"device": device_info,
|
||||
}
|
||||
# Définition de l'entité memory_used
|
||||
memory_used_entity = {
|
||||
"name": "memory_used_aorus",
|
||||
"type": "sensor",
|
||||
"unique_id": "memory_used_aorus_18:c0:4d:b5:65:74",
|
||||
"state_topic": "pilot/aorus/memory_used",
|
||||
"availability_topic": "pilot/aorus/memory_used/available",
|
||||
# "device_class": "memory",
|
||||
"unit_of_measurement": "MB",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:memory",
|
||||
"device": device_info,
|
||||
}
|
||||
|
||||
gpu_memory_usage_entity = {
|
||||
"name": "gpu_memory_usage",
|
||||
"type": "sensor",
|
||||
"unique_id": "gpu_memory_used_aorus_18:c0:4d:b5:65:74",
|
||||
"state_topic": "pilot/aorus/gpu_memory_usage/state",
|
||||
"availability_topic": "pilot/aorus/gpu_memory_usage/available",
|
||||
"unit_of_measurement": "MB",
|
||||
# "device_class": "memory",
|
||||
"unit_of_measurement": "MB",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:memory",
|
||||
"device": device_info,
|
||||
}
|
||||
|
||||
cpu_usage_entity = {
|
||||
"name": "cpu_usage_aorus",
|
||||
"type": "sensor",
|
||||
"unique_id": "cpu_usage_aorus_18:c0:4d:b5:65:74",
|
||||
"state_topic": "pilot/aorus/cpu_usage",
|
||||
"availability_topic": "pilot/aorus/cpu_usage/available",
|
||||
"unit_of_measurement": "%",
|
||||
"payload_available": "online",
|
||||
"payload_not_available": "offline",
|
||||
"icon": "mdi:memory",
|
||||
"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/{shutdown_entity['name']}/config",
|
||||
json.dumps(shutdown_entity),
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la configuration du capteur cpu_temp
|
||||
client.publish(
|
||||
f"{discovery_prefix}/sensor/{cpu_temp_entity['name']}/config",
|
||||
json.dumps(cpu_temp_entity),
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la configuration du capteur gpu_temp
|
||||
client.publish(
|
||||
f"{discovery_prefix}/sensor/{gpu_temp_entity['name']}/config",
|
||||
json.dumps(gpu_temp_entity),
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la configuration du capteur memory_used
|
||||
client.publish(
|
||||
f"{discovery_prefix}/sensor/{memory_used_entity['name']}/config",
|
||||
json.dumps(memory_used_entity),
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la disponibilité pour l'entité cpu_usage
|
||||
client.publish(
|
||||
f"{discovery_prefix}/sensor/{cpu_usage_entity['name']}/config",
|
||||
json.dumps(cpu_usage_entity),
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la configuration du capteur gpu_memory_usage
|
||||
client.publish(
|
||||
f"homeassistant/sensor/{gpu_memory_usage_entity['name']}/config",
|
||||
json.dumps(gpu_memory_usage_entity),
|
||||
retain=True,
|
||||
)
|
||||
|
||||
|
||||
# client.publish(f"{discovery_prefix}/sensor/{battery_entity['name']}/config", json.dumps(battery_entity), retain=True)
|
||||
|
||||
|
||||
def publish_availability(client):
|
||||
client.publish(
|
||||
shutdown_entity["availability_topic"],
|
||||
shutdown_entity["payload_available"],
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la disponibilité pour l'entité cpu_temp
|
||||
client.publish(
|
||||
cpu_temp_entity["availability_topic"],
|
||||
cpu_temp_entity["payload_available"],
|
||||
retain=True,
|
||||
)
|
||||
|
||||
# Publication de la disponibilité pour l'entité gpu_temp
|
||||
client.publish(
|
||||
gpu_temp_entity["availability_topic"],
|
||||
gpu_temp_entity["payload_available"],
|
||||
retain=True,
|
||||
)
|
||||
|
||||
# Publication de la disponibilité pour l'entité memory_used
|
||||
client.publish(
|
||||
memory_used_entity["availability_topic"],
|
||||
memory_used_entity["payload_available"],
|
||||
retain=True,
|
||||
)
|
||||
|
||||
client.publish(
|
||||
cpu_usage_entity["availability_topic"],
|
||||
cpu_usage_entity["payload_available"],
|
||||
retain=True,
|
||||
)
|
||||
# Publication de la disponibilité pour l'entité gpu_memory_usage
|
||||
client.publish(
|
||||
gpu_memory_usage_entity["availability_topic"],
|
||||
"online", # ou "offline" si le capteur n'est pas disponible
|
||||
retain=True,
|
||||
)
|
||||
|
||||
# client.publish(
|
||||
# battery_entity["availability_topic"],
|
||||
# battery_entity["payload_available"],
|
||||
# retain=True,
|
||||
# )
|
||||
print("Published availability for all entities")
|
||||
|
||||
|
||||
# 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)
|
||||
# threading.Timer(update_frequency, publish_sensor_data, [client]).start()
|
||||
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
if rc == 0:
|
||||
print("Connected with result code {rc}")
|
||||
client.subscribe(shutdown_entity["command_topic"])
|
||||
publish_discovery_messages(client)
|
||||
publish_availability(client)
|
||||
# publish_sensor_data(
|
||||
# client
|
||||
# ) # Démarre la première publication des données du capteur
|
||||
|
||||
# Publier l'état "ON" pour le switch au démarrage
|
||||
client.publish(
|
||||
shutdown_entity["state_topic"], shutdown_entity["payload_on"], retain=True
|
||||
)
|
||||
print(f"Set {shutdown_entity['name']} to ON")
|
||||
|
||||
|
||||
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)
|
||||
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,
|
||||
# )
|
||||
time.sleep(1)
|
||||
subprocess.run(["sudo", "shutdown", "-h", "now"])
|
||||
elif message.payload.decode() == shutdown_entity["payload_on"]:
|
||||
print("Received 'ON' command - no action for 'ON'")
|
||||
def publish_sensor_values(client):
|
||||
cpu_temp = get_cpu_temperature()
|
||||
if cpu_temp is not None:
|
||||
client.publish(cpu_temp_entity["state_topic"], round(cpu_temp, 1), retain=True)
|
||||
|
||||
gpu_temp = get_gpu_temperature()
|
||||
if gpu_temp is not None:
|
||||
client.publish(gpu_temp_entity["state_topic"], round(gpu_temp, 1), retain=True)
|
||||
|
||||
memory_used = get_memory_used()
|
||||
if memory_used is not None:
|
||||
client.publish(memory_used_entity["state_topic"], memory_used, retain=True)
|
||||
|
||||
cpu_usage = get_cpu_usage()
|
||||
if cpu_usage is not None:
|
||||
client.publish(cpu_usage_entity["state_topic"], cpu_usage, retain=True)
|
||||
gpu_memory_usage = get_gpu_memory_usage()
|
||||
|
||||
if gpu_memory_usage is not None:
|
||||
client.publish(gpu_memory_usage_entity["state_topic"], gpu_memory_usage, retain=True)
|
||||
# def get_battery_level():
|
||||
# try:
|
||||
# with open("/sys/class/power_supply/BAT0/capacity", "r") as file:
|
||||
# return file.read().strip()
|
||||
# except Exception as e:
|
||||
# print(f"Error reading battery level: {e}")
|
||||
# return None
|
||||
|
||||
|
||||
# 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
|
||||
publish_sensor_values(client) # Publier les valeurs des capteurs
|
||||
time.sleep(update_frequency) # Attendre avant la prochaine mise à jour
|
||||
except KeyboardInterrupt:
|
||||
print("Script interrupted, closing MQTT connection")
|
||||
# Publier l'état "unavailable" pour les entités
|
||||
client.publish(
|
||||
shutdown_entity["availability_topic"],
|
||||
shutdown_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
client.publish(
|
||||
cpu_temp_entity["availability_topic"],
|
||||
cpu_temp_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
client.publish(
|
||||
gpu_temp_entity["availability_topic"],
|
||||
gpu_temp_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
client.publish(
|
||||
memory_used_entity["availability_topic"],
|
||||
memory_used_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
|
||||
client.publish(
|
||||
cpu_usage_entity["availability_topic"],
|
||||
cpu_usage_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
client.publish(
|
||||
gpu_memory_usage_entity["availability_topic"],
|
||||
gpu_memory_usage_entity["payload_not_available"],
|
||||
retain=True,
|
||||
)
|
||||
# client.publish(
|
||||
# battery_entity["availability_topic"],
|
||||
# battery_entity["payload_not_available"],
|
||||
# retain=True,
|
||||
# )
|
||||
# Fermer la connexion MQTT proprement
|
||||
client.disconnect()
|
||||
Reference in New Issue
Block a user