premier envoie

This commit is contained in:
2024-04-14 07:13:49 +02:00
parent 537f1acde4
commit c14ea74287
5 changed files with 585 additions and 79 deletions

148
README.md
View File

@@ -1,93 +1,83 @@
# pilot # Aorus
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin http://10.0.0.200/pilot/pilot.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](http://10.0.0.200/pilot/pilot/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description ## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges installe un service qui creer des entites pour home assistant:
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - etat de la batterie
- button pour eteindre le pc
## Visuals ## Prérequis
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
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 ## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage ```
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. git clone http://10.0.1.200/pilot/aorus.git
```
## Support ```
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. cd aorus
```
Création de l'environnement:
## Roadmap ```
If you have ideas for releases in the future, it is a good idea to list them in the README. python3 -m venv monenv
```
Activation de l'environnement:
```
source monenv/bin/activate
```
Installation des paquets additionnels:
```
pip install -r requirements.txt
```
## Test du programme
## Contributing ```
State if you are open to contributions and what your requirements are for accepting them. python3 main.py
```
Sortie de l'environnement:
```
deactivate
```
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. ## Installation en temps que service
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. authorisation de shutdown:
## Authors and acknowledgment ```
Show your appreciation to those who have contributed to the project. sudo visudo
```
```
gilles ALL=(ALL) NOPASSWD: /sbin/shutdown
```
Installation du service:
## License ```
For open source projects, say how it is licensed. sudo cp mqtt_pilot.service /etc/systemd/system/
```
## Project status ```
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. sudo systemctl daemon-reload
```
```
sudo systemctl enable mqtt_pilot.service
```
```
sudo systemctl start mqtt_pilot.service
```
```
sudo systemctl status mqtt_pilot.service
```

400
main.py Normal file
View 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()

17
mqtt_pilot.service Normal file
View File

@@ -0,0 +1,17 @@
[Unit]
Description=MQTT Pilot Service
After=network.target
# Ajouter un délai après le démarrage du réseau
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=gilles
# Délai avant de démarrer le service
ExecStartPre=/bin/sleep 60
ExecStart=/home/gilles/aorus/monenv/bin/python3 /home/gilles/aorus/main.py
Restart=on-failure
RestartSec=30
ExecStopPost=/home/gilles/aorus/monenv/bin/python3 /home/gilles/aorus/mqtt_unvai.py
[Install]
WantedBy=multi-user.target

96
mqtt_unvai.py Normal file
View File

@@ -0,0 +1,96 @@
import paho.mqtt.client as mqtt
# Paramètres MQTT
mqtt_broker_ip_address = "10.0.0.3"
mqtt_port = 1883
mqtt_username = ""
mqtt_password = ""
# Configuration des entités
shutdown_entity = {
"availability_topic": "pilot/aorus/shutdown/available",
"payload_not_available": "offline",
}
# battery_entity = {
# "availability_topic": "pilot/aorus/battery/available",
# "payload_not_available": "offline",
# }
cpu_temperature_entity = {
"availability_topic": "pilot/aorus/cpu_temp/available",
"payload_not_available": "offline",
}
gpu_temperature_entity = {
"availability_topic": "pilot/aorus/gpu_temp/available",
"payload_not_available": "offline",
}
gpu_memory_entity = {
"availability_topic": "pilot/aorus/gpu_memory_usage/available",
"payload_not_available": "offline",
}
memory_usage_entity = {
"availability_topic": "pilot/aorus/memory_used/available",
"payload_not_available": "offline",
}
cpu_usage_entity = {
"availability_topic": "pilot/aorus/cpu_usage/available",
"payload_not_available": "offline",
}
# 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,
# )
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")
# 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)
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()

3
requirement.txt Normal file
View File

@@ -0,0 +1,3 @@
paho-mqtt==1.5.1
psutil==5.9.8
pynvml==11.5.0