version multi computer
This commit is contained in:
201
README.html
Normal file
201
README.html
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Aorus</title>
|
||||||
|
<style>
|
||||||
|
/* From extension vscode.github */
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.vscode-dark img[src$=\#gh-light-mode-only],
|
||||||
|
.vscode-light img[src$=\#gh-dark-mode-only],
|
||||||
|
.vscode-high-contrast:not(.vscode-high-contrast-light) img[src$=\#gh-light-mode-only],
|
||||||
|
.vscode-high-contrast-light img[src$=\#gh-dark-mode-only] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.task-list-item {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-list-item-checkbox {
|
||||||
|
margin-left: -20px;
|
||||||
|
vertical-align: middle;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--color-note: #0969da;
|
||||||
|
--color-tip: #1a7f37;
|
||||||
|
--color-warning: #9a6700;
|
||||||
|
--color-severe: #bc4c00;
|
||||||
|
--color-caution: #d1242f;
|
||||||
|
--color-important: #8250df;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--color-note: #2f81f7;
|
||||||
|
--color-tip: #3fb950;
|
||||||
|
--color-warning: #d29922;
|
||||||
|
--color-severe: #db6d28;
|
||||||
|
--color-caution: #f85149;
|
||||||
|
--color-important: #a371f7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.markdown-alert {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: inherit;
|
||||||
|
border-left: .25em solid #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert>:first-child {
|
||||||
|
margin-top: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert>:last-child {
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert .markdown-alert-title {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 500;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert .markdown-alert-title .octicon {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
display: inline-block;
|
||||||
|
overflow: visible !important;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-note {
|
||||||
|
border-left-color: var(--color-note);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-note .markdown-alert-title {
|
||||||
|
color: var(--color-note);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-important {
|
||||||
|
border-left-color: var(--color-important);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-important .markdown-alert-title {
|
||||||
|
color: var(--color-important);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-warning {
|
||||||
|
border-left-color: var(--color-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-warning .markdown-alert-title {
|
||||||
|
color: var(--color-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-tip {
|
||||||
|
border-left-color: var(--color-tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-tip .markdown-alert-title {
|
||||||
|
color: var(--color-tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-caution {
|
||||||
|
border-left-color: var(--color-caution);
|
||||||
|
}
|
||||||
|
|
||||||
|
.markdown-alert.markdown-alert-caution .markdown-alert-title {
|
||||||
|
color: var(--color-caution);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="vscode-body vscode-light">
|
||||||
|
<h1 id="aorus">Aorus</h1>
|
||||||
|
<h2 id="description">Description</h2>
|
||||||
|
<p>installe un service qui creer des entites pour home assistant:</p>
|
||||||
|
<ul>
|
||||||
|
<li>etat de la batterie</li>
|
||||||
|
<li>button pour eteindre le pc</li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="prérequis">Prérequis</h2>
|
||||||
|
<p>installation de python3 et de python-env:</p>
|
||||||
|
<pre><code>sudo apt install python3-venv
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>python3 -m venv monenv
|
||||||
|
</code></pre>
|
||||||
|
<p>activation de l'environnement:</p>
|
||||||
|
<pre><code>source monenv/bin/activate
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="installation">Installation</h2>
|
||||||
|
<pre><code>git clone http://10.0.1.200/pilot/aorus.git
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>cd aorus
|
||||||
|
</code></pre>
|
||||||
|
<p>Création de l'environnement:</p>
|
||||||
|
<pre><code>python3 -m venv monenv
|
||||||
|
</code></pre>
|
||||||
|
<p>Activation de l'environnement:</p>
|
||||||
|
<pre><code>source monenv/bin/activate
|
||||||
|
</code></pre>
|
||||||
|
<p>Installation des paquets additionnels:</p>
|
||||||
|
<pre><code>pip install -r requirements.txt
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="test-du-programme">Test du programme</h2>
|
||||||
|
<pre><code>python3 main.py
|
||||||
|
</code></pre>
|
||||||
|
<p>Sortie de l'environnement:</p>
|
||||||
|
<pre><code>deactivate
|
||||||
|
</code></pre>
|
||||||
|
<h2 id="installation-en-temps-que-service">Installation en temps que service</h2>
|
||||||
|
<p>authorisation de shutdown:</p>
|
||||||
|
<pre><code>sudo visudo
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
|
||||||
|
</code></pre>
|
||||||
|
<p>Installation du service:</p>
|
||||||
|
<pre><code>sudo cp mqtt_pilot.service /etc/systemd/system/
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>sudo systemctl daemon-reload
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>sudo systemctl enable mqtt_pilot.service
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>sudo systemctl start mqtt_pilot.service
|
||||||
|
</code></pre>
|
||||||
|
<pre><code>sudo systemctl status mqtt_pilot.service
|
||||||
|
</code></pre>
|
||||||
|
<p>lancer l'installation du service:</p>
|
||||||
|
<pre><code>sudo ./install.sh
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
16
README.md
16
README.md
@@ -5,6 +5,12 @@
|
|||||||
installe un service qui creer des entites pour home assistant:
|
installe un service qui creer des entites pour home assistant:
|
||||||
- etat de la batterie
|
- etat de la batterie
|
||||||
- button pour eteindre le pc
|
- button pour eteindre le pc
|
||||||
|
- reboot
|
||||||
|
- eteindre l'ecran
|
||||||
|
- cpu
|
||||||
|
- memory
|
||||||
|
- adresse ip
|
||||||
|
- cpu frequency
|
||||||
|
|
||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
@@ -56,15 +62,17 @@ deactivate
|
|||||||
|
|
||||||
## Installation en temps que service
|
## Installation en temps que service
|
||||||
|
|
||||||
authorisation de shutdown:
|
authorisation de shutdown: ajouter a la fin du fichier
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo visudo
|
sudo visudo
|
||||||
```
|
```
|
||||||
```
|
```
|
||||||
gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
|
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/
|
sudo cp mqtt_pilot.service /etc/systemd/system/
|
||||||
@@ -81,3 +89,7 @@ sudo systemctl start mqtt_pilot.service
|
|||||||
```
|
```
|
||||||
sudo systemctl status mqtt_pilot.service
|
sudo systemctl status mqtt_pilot.service
|
||||||
```
|
```
|
||||||
|
lancer l'installation du service:
|
||||||
|
```
|
||||||
|
sudo ./install.sh
|
||||||
|
```
|
||||||
|
|||||||
22
install.sh
Executable file
22
install.sh
Executable file
@@ -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."
|
||||||
535
main_prog.py
Normal file
535
main_prog.py
Normal file
@@ -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 <discovery_prefix>/<component>/[<node_id>/]<object_id>/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()
|
||||||
@@ -8,10 +8,12 @@ After=network-online.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
User=gilles
|
User=gilles
|
||||||
# Délai avant de démarrer le service
|
# Délai avant de démarrer le service
|
||||||
ExecStartPre=/bin/sleep 60
|
ExecStartPre=/bin/sleep 30
|
||||||
ExecStart=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/main.py
|
ExecStart=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/main_prog.py
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=30
|
RestartSec=30
|
||||||
ExecStopPost=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/mqtt_unvai.py
|
ExecStopPost=/home/gilles/pilot/monenv/bin/python3 /home/gilles/pilot/mqtt_unvai.py
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
251
mqtt_unvai.py
251
mqtt_unvai.py
@@ -9,87 +9,222 @@ mqtt_port = 1883
|
|||||||
mqtt_username = ""
|
mqtt_username = ""
|
||||||
mqtt_password = ""
|
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
|
# Configuration des entités
|
||||||
shutdown_entity = {
|
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",
|
"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 = {
|
battery_entity = {
|
||||||
# "availability_topic": f"pilot/{hostname}/battery/available",
|
"name": f"battery_{device_name}",
|
||||||
# "payload_not_available": "offline",
|
"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 = {
|
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",
|
"payload_not_available": "offline",
|
||||||
|
"icon": "mdi:thermometer",
|
||||||
|
"device": device_info,
|
||||||
|
"update_interval": 20
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu_temperature_entity = {
|
cpu_usage_entity = {
|
||||||
"availability_topic": f"pilot/{hostname}/gpu_temp/available",
|
"name": f"cpu_usage_{device_name}",
|
||||||
"payload_not_available": "offline",
|
"type": "sensor",
|
||||||
}
|
"unique_id": f"cpu_usage_{device_name}_{mac_address}",
|
||||||
gpu_memory_entity = {
|
"state_topic": f"pilot/{device_name}/cpu_usage/state",
|
||||||
"availability_topic": f"pilot/{hostname}/gpu_memory_usage/available",
|
"unit_of_measurement": "%",
|
||||||
|
"device_class": "power",
|
||||||
|
"availability_topic": f"pilot/{device_name}/cpu_usage/available",
|
||||||
|
"payload_available": "online",
|
||||||
"payload_not_available": "offline",
|
"payload_not_available": "offline",
|
||||||
|
"icon": "mdi:chip",
|
||||||
|
"device": device_info,
|
||||||
|
"update_interval": 10
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_usage_entity = {
|
memory_usage_entity = {
|
||||||
"availability_topic": f"pilot/{hostname}/memory_used/available",
|
"name": f"memory_usage_{device_name}",
|
||||||
"payload_not_available": "offline",
|
"type": "sensor",
|
||||||
}
|
"unique_id": f"memory_usage_{device_name}_{mac_address}",
|
||||||
cpu_usage_entity = {
|
"state_topic": f"pilot/{device_name}/memory_usage/state",
|
||||||
"availability_topic": f"pilot/{hostname}/cpu_usage/available",
|
"unit_of_measurement": "%",
|
||||||
|
# "device_class": "memory",
|
||||||
|
"availability_topic": f"pilot/{device_name}/memory_usage/available",
|
||||||
|
"payload_available": "online",
|
||||||
"payload_not_available": "offline",
|
"payload_not_available": "offline",
|
||||||
|
"icon": "mdi:memory",
|
||||||
|
"device": device_info,
|
||||||
|
"update_interval": 10
|
||||||
}
|
}
|
||||||
|
|
||||||
# Fonction pour publier l'état "unavailable" pour les entités
|
cpu_frequency_entity = {
|
||||||
def publish_unavailability(client):
|
"name": f"cpu_frequency_{device_name}",
|
||||||
client.publish(
|
"type": "sensor",
|
||||||
shutdown_entity["availability_topic"],
|
"unique_id": f"cpu_frequency_{device_name}_{mac_address}",
|
||||||
shutdown_entity["payload_not_available"],
|
"state_topic": f"pilot/{device_name}/cpu_frequency/state",
|
||||||
retain=True,
|
"unit_of_measurement": "GHz",
|
||||||
)
|
"device_class": "frequency",
|
||||||
# client.publish(
|
"availability_topic": f"pilot/{device_name}/cpu_frequency/available",
|
||||||
# battery_entity["availability_topic"],
|
"payload_available": "online",
|
||||||
# battery_entity["payload_not_available"],
|
"payload_not_available": "offline",
|
||||||
# retain=True,
|
"icon": "mdi:speedometer",
|
||||||
# )
|
"device": device_info,
|
||||||
|
"update_interval": 20
|
||||||
|
}
|
||||||
|
|
||||||
client.publish(
|
ip_address_entity = {
|
||||||
cpu_temperature_entity["availability_topic"],
|
"name": f"ip_address_{device_name}",
|
||||||
cpu_temperature_entity["payload_not_available"],
|
"type": "sensor",
|
||||||
retain=True,
|
"unique_id": f"ip_address_{device_name}_{mac_address}",
|
||||||
)
|
"state_topic": f"pilot/{device_name}/ip_address/state",
|
||||||
client.publish(
|
"availability_topic": f"pilot/{device_name}/ip_address/available",
|
||||||
gpu_temperature_entity["availability_topic"],
|
#"device_class": "connectivity",
|
||||||
gpu_temperature_entity["payload_not_available"],
|
"payload_available": "online",
|
||||||
retain=True,
|
"payload_not_available": "offline",
|
||||||
)
|
"icon": "mdi:ip",
|
||||||
client.publish(
|
"device": device_info,
|
||||||
gpu_memory_entity["availability_topic"],
|
"update_interval": 60
|
||||||
gpu_memory_entity["payload_not_available"],
|
}
|
||||||
retain=True,
|
|
||||||
)
|
cpu_frequency_slider_entity = {
|
||||||
client.publish(
|
"name": f"cpu_frequency_slider_{device_name}",
|
||||||
cpu_usage_entity["availability_topic"],
|
"type": "number",
|
||||||
cpu_usage_entity["payload_not_available"],
|
"unique_id": f"cpu_frequency_slider_{device_name}_{mac_address}",
|
||||||
retain=True,
|
"command_topic": f"pilot/{device_name}/cpu_frequency_slider/set",
|
||||||
)
|
"state_topic": f"pilot/{device_name}/cpu_frequency_slider/state",
|
||||||
client.publish(
|
"availability_topic": f"pilot/{device_name}/cpu_frequency_slider/available",
|
||||||
memory_usage_entity["availability_topic"],
|
"payload_available": "online",
|
||||||
memory_usage_entity["payload_not_available"],
|
"payload_not_available": "offline",
|
||||||
retain=True,
|
"min": 0.5,
|
||||||
)
|
"max": 3.0,
|
||||||
print("Published unavailability for all entities")
|
"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
|
# Fonction appelée lors de la connexion au broker MQTT
|
||||||
def on_connect(client, userdata, flags, rc):
|
def on_connect(client, userdata, flags, rc):
|
||||||
if rc == 0:
|
if rc == 0:
|
||||||
print("Connected with result code {rc}")
|
print(f"Connected with result code {rc}")
|
||||||
publish_unavailability(client)
|
deactivate_entities(client)
|
||||||
client.disconnect() # Déconnecter après la publication
|
client.disconnect() # Déconnecter après la publication
|
||||||
|
|
||||||
|
|
||||||
# Configuration et démarrage du client MQTT
|
# Configuration et démarrage du client MQTT
|
||||||
client = mqtt.Client()
|
client = mqtt.Client()
|
||||||
client.username_pw_set(mqtt_username, mqtt_password)
|
client.username_pw_set(mqtt_username, mqtt_password)
|
||||||
|
|||||||
Reference in New Issue
Block a user