Allsky quep

Répondre
quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 13:22

Ce fil a pour but de présenter le matériel et les logiciels utilisés pour arriver jusqu’à la version actuelle de ma allsky.
Beaucoup de tâtonnement et de recherche, notamment pour la partie script.
Je ne traiterais pas de l'installation du logiciel allsky, les documentations disponibles sont très bien faites sur le site.

IMG_6820.JPG
IMG_6994.JPG
IMG_6996.JPG
IMG_6997.JPG
IMG_6998.jpg

Matériel

- Raspberry pi 4 - 4Go

- Hat POE

- Raspberry HQ imx477

- Fisheye 1.55mm

- Boitier étanche 260x160

- Connecteur RJ étanche

- Connecteur d'alimentation étanche

- Fond de boitier 250x150

- Dôme plexi

- Relais 12v

- Résistance chaufante 12v

- Protection capteur exterieur

- Capteurs BME280 3.3v et 5v pour différencier l'adresse

- Adaptateur SATA

- SSD 250Go

- Lot d'entretoise M2.5

- Câbles Dupont
Dernière modification par quep le 08 nov. 2024, 13:39, modifié 1 fois.

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 13:22

Logiciels

Deux logiciels m’intéressait pour mon modèle mais j'ai choisi le logiciel Allsky, de Thomas Jacquin par rapport à indi-allsky, je préfère l'interface utilisateur.
Les deux logiciels sont activement développés.

En plus du logiciel de base il existe des modules à installer, suivant les capteurs que l'on souhaite utiliser et les fonctionnalités recherchées.

J'ai choisi d'installer trois capteurs, deux BME280 pour la température intérieure et extérieure, ainsi qu'un capteur IR pour déterminer la couverture nuageuse. Ce dernier n'est pas encore en fonctionnement, la calibration n'est pas évidente donc je ne le traiterais pas ici.

Je souhaitais en plus de la surveillance du ciel, pouvoir avoir des représentations graphiques du fonctionnement du raspberry et des capteurs. J'ai choisi Influxdb/ comme gestionnaire de base de données et Grafana comme plateforme de visualisation. Ce n'est pas particulièrement utile donc parfaitement indispensable :)

Schéma_cablage.jpg
Schéma_cablage.jpg (161.98 Kio) Consulté 6356 fois

Présentation du fonctionnement et script

Le raspberry est alimenté via POE par un câble téléphonique 12 paires de 30m (8 paires utilisées pour le RJ) avec un switch POE au bout.
La résistance chauffante est alimentée en 12v par un autre câble téléphonique 8 paires de 30m (4 paires utilisées, 2+ et 2-) avec un transformateur au bout. Elle est asservie par le relais installé, suivant la température captée par le capteur extérieur.
Un des modules ajouté dans le logiciel modifie la position (haute ou basse, 0v ou 5v) d'un des GPIO (le 4) pour déclencher le relais 12v.

Les trois capteurs sont connectés au bus I2C sur les GPIO du raspberry.
- 1 BME280 en 3,3v
- 1 BME280 en 5v
- 1 MLX90614 en 5V

L’intérêt d'avoir les deux capteurs alimentés différemment est de pouvoir différencier leurs adresses sur le bus I2C. Un prendra la valeur 0x76 et l'autre 0x77.
Dernière modification par quep le 08 nov. 2024, 13:41, modifié 2 fois.

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 13:24

Installation des paquets

Version de Raspbian : Bookworm
Installation du SSD en 64 bits sans interface utilisateur avec l'utilitaire raspberry pi imager.
Configuration, lors de la préparation avec le logiciel, d'un utilisateur avec mot de passe et activation du ssh pour une gestion à distance.
Il est également possible de modifier le nom du raspberry pi pour la connexion en ssh.

Dans mon cas, après l'allumage du RPI, l'adresse est restée en http://raspberrypi.local
L'adresse changera à l'installation de la partie allsky, en http://allsky.loca

Le script qui me permet de récupérer les différentes données capteurs a été réalisé par ChatGPT, en python. Mes maigres connaissances en programmation ont permis quelques débogages mais l'essentiel a été réalisé par l'IA.

Les données collectées sont enregistrées dans un fichier JSON local. L’emplacement de l’enregistrement est fait dans un dossier particulier du logiciel car cela permet de récupérer les données de mon script, pour les afficher sur la surcouche de l’image du ciel.
Le script est lancé à intervalle régulier par un cron.

Le cron lance le script allsky.sh toutes les 3 minutes, pour créer l'environnement python et lancer le script allsky.py dans cet environnement. A la fin de l'exécution du script allsky.py, allsky.sh désactive l'environnement.

Installation des paquets Influxdb, Grafana et création des scripts

Installation des paquets :

# Mise à jour et installation des paquets nécessaires

Code : Tout sélectionner

sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install -y curl wget gnupg i2c-tools python3-smbus python3-pip git virtualenv python3-virtualenv
# Configuration de la France comme pays pour le Wi-Fi

Code : Tout sélectionner

sudo raspi-config nonint do_wifi_country FR
# Configuration Timezone

Code : Tout sélectionner

sudo raspi-config nonint do_change_timezone Europe/Paris
# Activation de l'interface I2C

Code : Tout sélectionner

sudo raspi-config nonint do_i2c 0
# Téléchargement et installation d'InfluxDB

Code : Tout sélectionner

curl -LO https://download.influxdata.com/influxdb/releases/influxdb2_2.7.6-1_arm64.deb
sudo dpkg -i influxdb2_2.7.6-1_arm64.deb
# Téléchargement et installation du CLI InfluxDB

Code : Tout sélectionner

wget https://download.influxdata.com/influxdb/releases/influxdb2-client-2.7.5-linux-arm64.tar.gz
tar xvzf ./influxdb2-client-2.7.5-linux-arm64.tar.gz
sudo cp ./influx /usr/local/bin/
# Suppression des fichiers téléchargés

Code : Tout sélectionner

rm influxdb2_2.7.6-1_arm64.deb
rm influxdb2-client-2.7.5-linux-arm64.tar.gz
rm README.md
rm LICENSE
# Configuration du dépôt Grafana

Code : Tout sélectionner

sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
# Mise à jour des paquets et installation de Grafana

Code : Tout sélectionner

sudo apt-get update
sudo apt-get install -y grafana
# Activation et démarrage du service Grafana

Code : Tout sélectionner

sudo /bin/systemctl enable grafana-server
sudo /bin/systemctl start grafana-server
# Création du script

Code : Tout sélectionner

mkdir -p /home/quep/script
cd /home/quep/script
nano allsky.py

Code : Tout sélectionner

import smbus2
import bme280
import json
import os
import datetime
import psutil
from influxdb_client import InfluxDBClient, Point, WriteOptions
from influxdb_client.client.write_api import SYNCHRONOUS
import RPi.GPIO as GPIO
import re

# Define the I2C bus number
bus_number = 1

# Define the addresses of the two sensors
sensor1_address = 0x77
sensor2_address = 0x76

# Initialize the I2C bus
bus = smbus2.SMBus(bus_number)

# Read data from the first sensor
calibration_params = bme280.load_calibration_params(bus, sensor1_address)
data1 = bme280.sample(bus, sensor1_address, calibration_params)
temperature1 = round(data1.temperature, 2)
pressure1 = round(data1.pressure, 2)

# Read data from the second sensor
calibration_params = bme280.load_calibration_params(bus, sensor2_address)
data2 = bme280.sample(bus, sensor2_address, calibration_params)
temperature2 = round(data2.temperature, 2)
pressure2 = round(data2.pressure, 2)

# Read disk usage
disk_usage = psutil.disk_usage("/")
total_size = round(disk_usage.total / (1024 ** 3), 2)  # Convert to GB
used_space = round(disk_usage.used / (1024 ** 3), 2)  # Convert to GB
free_space = round(disk_usage.free / (1024 ** 3), 2)  # Convert to GB

# Read network I/O counters
net_io = psutil.net_io_counters()
download = net_io.bytes_recv
upload = net_io.bytes_sent

# Convert bytes to MB and round to integer
download_mb = int(download / (1024 ** 2))  # Convert to MB and cast to integer
upload_mb = int(upload / (1024 ** 2))      # Convert to MB and cast to integer

# Read CPU temperature
cpu_temp = psutil.sensors_temperatures().get('cpu_thermal')[0].current

# Read system uptime
uptime_seconds = int((datetime.datetime.now() - datetime.datetime.fromtimestamp(psutil.boot_time())).total_seconds())

uptime_hours = uptime_seconds // 3600
uptime_minutes = (uptime_seconds % 3600) // 60
uptime_days = uptime_seconds // 86400  # Corrected this line (1 day = 86400 seconds)
uptime_years = uptime_days // 365  # Approximation (1 year = 365 days)

# Define the dictionary to store the sensor data
sensor_data = {
    'measurement': 'allsky',
    'tags': {},
    'fields': {
        'AS_TEMPEXT': temperature1,
        'AS_PRESSEXT': pressure1,
        'AS_TEMPINT': temperature2,
        'AS_PRESSINT': pressure2,
        'AS_CPUTEMP': cpu_temp,
        'AS_TOTALSIZE': total_size,
        'AS_USEDSPACE': used_space,
        'AS_FREESPACE': free_space,
        'AS_CPUUSAGE': psutil.cpu_percent(interval=1),
        'AS_RAMUSAGE': psutil.virtual_memory().percent,
        'AS_UPTIME_HOURS': uptime_hours,
        'AS_UPTIME_MINUTES': uptime_minutes,
        'AS_DOWNLOAD': download_mb,
        'AS_UPLOAD': upload_mb,
        'AS_UPTIME_YEARS': uptime_years,
        'AS_UPTIME_DAYS': uptime_days
    }
}

# Load dew control data from allskydew.json
allskydew_path = '/home/quep/allsky/config/overlay/extra/allskydew.json'
if os.path.exists(allskydew_path):
    with open(allskydew_path, 'r') as dew_file:
        dew_data = json.load(dew_file)
        sensor_data['fields']['AS_DEWCONTROLDEW'] = float(dew_data['AS_DEWCONTROLDEW'])
        sensor_data['fields']['AS_DEWCONTROLHEATER'] = dew_data['AS_DEWCONTROLHEATER']

# Configure the InfluxDB connection
influxdb_url = 'http://localhost:8086'
influxdb_token = 'XXXXXXXXXX'
influxdb_org = 'XXXXXXXXX'
influxdb_bucket = 'XXXXXXXXX'

# Create the InfluxDB client
client = InfluxDBClient(url=influxdb_url, token=influxdb_token, org=influxdb_org)

# Write the data to InfluxDB
write_api = client.write_api(write_options=SYNCHRONOUS)
point = Point(sensor_data['measurement']).tag("location", "allsky")
for key, value in sensor_data['fields'].items():
    point.field(key, value)
write_api.write(bucket=influxdb_bucket, org=influxdb_org, record=point)

# Define the directory path
directory_path = os.path.expanduser('/home/quep/allsky/config/overlay/extra/')

# Create the directory if it does not exist
os.makedirs(directory_path, exist_ok=True)

# Save the sensor data to a JSON file
file_path = os.path.join(directory_path, 'allsky_quep.json')
with open(file_path, 'w') as file:
    json.dump(sensor_data['fields'], file, indent=4)

print(f"Sensor data saved to {file_path}")
# Création du cron

Code : Tout sélectionner

(crontab -l 2>/dev/null; echo "*/3 * * * * /home/quep/script/allsky.sh") | crontab -
ou

Code : Tout sélectionner

crontab -e
et insérer la ligne

Code : Tout sélectionner

/3 * * * * /home/quep/script/allsky.sh

# création de l'environnement venv
# remonter à la racine de l'utilisateur # Création de l'environnement dans le dossier

Code : Tout sélectionner

python3 -m venv script/

#Activation de l'environnement dans le dossier

Code : Tout sélectionner

. /home/quep/script/bin/activate
# Installation des librairies

Code : Tout sélectionner

pip install rpi.bme280 influxdb-client psutil adafruit-circuitpython-bme280 adafruit-circuitpython-mlx90614 smbus2
# Désactivation de l'environnement

Code : Tout sélectionner

deactivate
# Création de allsky.sh

Code : Tout sélectionner

nano /home/quep/script/allsky.sh

Code : Tout sélectionner

#!/bin/bash
# Activate the virtual environment
. /home/quep/script/bin/activate

# Change directory to the script location
cd /home/quep/script

# Run the Python script
python3 allsky.py

# Deactivate the virtual environment
deactivate
# Ajout des droits d'execution

Code : Tout sélectionner

chmod +x /home/quep/script/allsky.sh
# Installation de samba

Code : Tout sélectionner

sudo apt install -y samba samba-common-bin
# Définition du block de partage Samba

Code : Tout sélectionner

CONFIG_BLOCK="[allsky]
path = /home/quep
writeable = yes
browseable = yes
public = no
"
# Ajout du block à la fin du fichier smb.conf

Code : Tout sélectionner

echo "$CONFIG_BLOCK" | sudo tee -a /etc/samba/smb.conf > /dev/null
# Redémarrage de samba

Code : Tout sélectionner

sudo systemctl restart smbd
#Téléchargement de allsky

Code : Tout sélectionner

git clone --recursive https://github.com/AllskyTeam/allsky.git
L'installation est à suivre avec la documentation de Allsky

#Téléchargement de allsky modules

Code : Tout sélectionner

git clone https://github.com/AllskyTeam/allsky-modules.git
L'installation est à suivre sur la documentation de Allsky modules
Dernière modification par quep le 08 nov. 2024, 13:44, modifié 4 fois.

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 13:24

Configuration InfluxDB et Grafana

InfluxDB

Un module InfluxDB est installable via les modules mais je n'ai pas réussi à le faire fonctionner. Je passe donc par le script précédent pour récupérer les données.

Un petit redémarrage et ensuite connexion à l'adresse http://localhost:8086 qui correspond à InfluxDB.

Il faut configurer le nom du compte et mot de passe, le nom de l'organisation et le nom du bucket à créer. (Il est possible de créer celui-ci par la suite)

A la fin de cette étape il faut absolument récupérer le Token d'influxDB.
Il servira à faire accepter la connexion à Influx des autres entités.

Je modifie ensuite les valeurs dans mon script :

# Configure the InfluxDB connection
influxdb_url = 'http://localhost:8086'
influxdb_token = 'token_influx'
influxdb_org = 'nom_org'
influxdb_bucket = 'nom_bucket'


Pour mon cas cela ressemble à ça:

# Configure the InfluxDB connection
influxdb_url = 'http://localhost:8086'
influxdb_token = 'TOKEN'
influxdb_org = 'quep'
influxdb_bucket = 'allsky'



Grafana

Se connecter à l'adresse http://localhost:3000 et procéder à la configuration du mot de passe et du nom d'utilisateur.

Dans l'interface de Grafana, se rendre dans l'onglet "Connections - Data sources" et cliquer sur "add new data source".

Choisir Influx comme base de données et remplir les champs comme suit:

Query : Flux
URL : http://localhost:8086
Auth : Basic Auth
InfluxDB Details : Nom de l'organisation, votre token précedemment récupéré, Default Bucket (mettre le nom de votre bucket)

Lorsque tout est rempli il faut cliquer sur "Save and test", si un encart vert indiquant que la source est trouvée c'est que la configuration est correcte.

Il faut ensuite se rendre dans le menu Dashboard afin d'en créer un nouveau. C'est dans celui-ci que l'on pourra ajouter des visualisations.
Dernière modification par quep le 07 janv. 2025, 17:07, modifié 3 fois.

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 13:25

Requêtes Influx dans Grafana

Je me suis encore appuyé sur ChatGPT pour la création des requêtes. Charge à moi d'insérer celles-ci dans les visualisations et de tâtonner pour trouver une visualisation qui fonctionne avec la requête.

En pièce-jointe, le json de mon dashboard, permettant une création sans trop de problèmes. La visualisation de eth0 ne fonctionne pas, il vaudra mieux la supprimer.
Dashboard_grafana.json
(32.78 Kio) Téléchargé 90 fois

Pour créer une visualisation il faut éditer le Dashboard --> "Add vizualisation". Dans le champ Influxdb recopier les requêtes et adapter la visualisation à droite de la fenêtre (Gauge, Stat, Histogram...) suivant la façon dont vous souhaiter visualiser les données.

Quelques requêtes Influx:

----------------------------------------------------------------
Température CPU - Utilisation du CPU et de la RAM

from(bucket: "allsky")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "allsky" and (r._field == "AS_CPUTEMP" or r._field == "AS_RAMUSAGE" or r._field == "AS_CPUUSAGE"))
|> group(columns: ["_measurement"])
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> drop(columns: ["_start", "_stop"])

---------------------------------------------------------------
Températures capteurs

from(bucket: "allsky")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "allsky" and (r._field == "AS_TEMPINT" or r._field == "AS_TEMPEXT"))
|> group(columns: ["_measurement"])
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> drop(columns: ["_start", "_stop"])


-----------------------------------------------------------------
Hygro intérieure et extérieure

from(bucket: "allsky")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "allsky" and (r._field == "AS_HUMIDINT" or r._field == "AS_HUMIDEXT"))
|> group(columns: ["_measurement"])
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> drop(columns: ["_start", "_stop"])

------------------------------------------------------------------
Résistante chauffante

from(bucket: "allsky")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "allsky" and r._field == "AS_DEWHEATER")
|> last()

choisir stat, text mode Value, unit -> string, value mapping pour les couleurs

-------------------------------------------------------------------
Temps depuis le démarrage de la allsky

from(bucket: "allsky")
|> range(start: -1h)
|> filter(fn: (r) => r._measurement == "allsky" and
(r._field == "AS_UPTIME_HOURS" or
r._field == "AS_UPTIME_MINUTES" or
r._field == "AS_UPTIME_DAYS" or
r._field == "AS_UPTIME_YEARS"))
|> last()
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> map(fn: (r) => ({
r with
uptime: (if r.AS_UPTIME_YEARS > 0 then string(v: r.AS_UPTIME_YEARS) + "y " else "") +
(if r.AS_UPTIME_DAYS > 0 then string(v: r.AS_UPTIME_DAYS) + "d " else "") +
string(v: r.AS_UPTIME_HOURS) + "h " +
string(v: r.AS_UPTIME_MINUTES) + "m"
}))
|> keep(columns: ["_time", "uptime"])


choisir une visualisation en stat.
-------------------------------------------------------------------
Je l'ajoute quand même si jamais un bienfaiteur maitrise les requêtes Influx :pray:

Dowload et Upload

from(bucket: "allsky")
|> range(start: -1h) // Adjust time range as needed
|> filter(fn: (r) => r._measurement == "allsky" and (r._field == "AS_DOWNLOAD" or r._field == "AS_UPLOAD"))
|> group(columns: ["_measurement"]) // Group by measurement
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
|> drop(columns: ["_start", "_stop"])


--------------------------------------------------------------------
Espace disque

from(bucket: "allsky")
|> range(start: -24h)
|> filter(fn: (r) => r._measurement == "allsky" and (r._field == "AS_USEDSPACE"))
|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
|> yield(name: "mean")

En cas de questions ou commentaires, je suis dispo :kiss:
Dernière modification par quep le 07 janv. 2025, 17:29, modifié 3 fois.

Avatar de l’utilisateur
fcouma
Messages : 3419
Inscription : 07 févr. 2021, 19:27
Localisation : 85

Allsky quep

Message par fcouma » 08 nov. 2024, 18:08

Bravo

C'est bien plus propre à l'intérieur que la mienne :closedeyes:

J'ai honte, mais elle fonctionne bien quand même :D

SBRCoach
Messages : 2487
Inscription : 16 nov. 2020, 21:04
Localisation : Aisne

Allsky quep

Message par SBRCoach » 08 nov. 2024, 18:09

fcouma a écrit :
08 nov. 2024, 18:08
Bravo

C'est bien plus propre à l'intérieur que la mienne :closedeyes:

J'ai honte, mais elle fonctionne bien quand même :D
C'est le principal

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 18:40

@fcouma comme @SBRCoach dit, le principal c’est que ça fonctionne comme tu veux ;)

Je suis plutôt bordélique d’habitude mais là, pour une fois, je voulais faire un truc lisible et reproductible.

SBRCoach
Messages : 2487
Inscription : 16 nov. 2020, 21:04
Localisation : Aisne

Allsky quep

Message par SBRCoach » 08 nov. 2024, 18:45

quep a écrit :
08 nov. 2024, 18:40
@fcouma comme @SBRCoach dit, le principal c’est que ça fonctionne comme tu veux ;)

Je suis plutôt bordélique d’habitude mais là, pour une fois, je voulais faire un truc lisible et reproductible.
Beau boulot !

Comme on dit "Un bureau bien rangé, est le signe d'un esprit dérangé" ;)

quep
Messages : 243
Inscription : 22 mai 2020, 22:55
Localisation : Rennes

Allsky quep

Message par quep » 08 nov. 2024, 18:47

Merci :)
SBRCoach a écrit :
08 nov. 2024, 18:45
Un bureau bien rangé, est le signe d'un esprit dérangé"
je ne connaissais pas, j’aime bien :D

Répondre

Revenir à « Satellites, météores et autres phénomènes transitoires »