Création du projet DaliACLI
- CLI PowerShell pour la gestion des sorties DALI adressable (ECxLightDaliA) - Action Read : rapport CSV des configurations (une ligne par output) - Action Write : modification des propriétés via POST JSON - Fallback curl.exe -k pour les automates avec problèmes SSL
This commit is contained in:
235
DaliACLI.ps1
Normal file
235
DaliACLI.ps1
Normal file
@@ -0,0 +1,235 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
CLI DALI pour automates Distech Controls Eclypse.
|
||||
Lecture et ecriture des configurations de sorties DALI adressable (ECxLightDaliA).
|
||||
|
||||
.DESCRIPTION
|
||||
DaliACLI permet de gerer les configurations DALI adressable sur des automates
|
||||
Distech Controls Eclypse en utilisant leur API REST v2.
|
||||
|
||||
Action READ : Lit la configuration des modules ECxLightDaliA de chaque automate
|
||||
et genere un fichier CSV avec une ligne par sortie (output).
|
||||
|
||||
Action WRITE : Modifie les proprietes des sorties DALI a partir du CSV.
|
||||
Toutes les proprietes de chaque ligne sont reecrites.
|
||||
|
||||
.PARAMETER Action
|
||||
Action a effectuer :
|
||||
Read - Lire la configuration et generer un CSV de sortie
|
||||
Write - Ecrire les proprietes depuis le CSV vers les automates
|
||||
|
||||
.PARAMETER CsvInput
|
||||
Chemin vers le fichier CSV d'entree (separateur point-virgule).
|
||||
Pour Read : colonnes minimales Hostname, Current Ip, HttpPort, HttpsPort.
|
||||
Pour Write : CSV enrichi genere par l'action Read.
|
||||
|
||||
.PARAMETER Username
|
||||
Nom d'utilisateur pour l'authentification API (defaut: admin).
|
||||
Peut etre surcharge par la colonne Username du CSV.
|
||||
|
||||
.PARAMETER Password
|
||||
Mot de passe pour l'authentification API (defaut: vide).
|
||||
Peut etre surcharge par la colonne Password du CSV.
|
||||
|
||||
.EXAMPLE
|
||||
.\DaliACLI.ps1 -Action Read -CsvInput ".\automates.csv"
|
||||
|
||||
Lit la configuration DALI de tous les automates listes dans le CSV.
|
||||
Genere un fichier dali_YYYY-MM-DD_HHhMM.csv dans le repertoire courant.
|
||||
|
||||
.EXAMPLE
|
||||
.\DaliACLI.ps1 -Action Write -CsvInput ".\dali_2026-04-02_14h30.csv" -Password "MonMotDePasse"
|
||||
|
||||
Ecrit les proprietes du CSV vers les automates.
|
||||
|
||||
.EXAMPLE
|
||||
Get-Help .\DaliACLI.ps1 -Detailed
|
||||
|
||||
Affiche cette aide detaillee.
|
||||
|
||||
.NOTES
|
||||
Prerequis : PowerShell 5.1+ (inclus dans Windows 10/11)
|
||||
API : Distech Controls Eclypse REST API v2
|
||||
Securite : TLS 1.2, certificats auto-signes acceptes
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet("Read", "Write")]
|
||||
[string]$Action,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[string]$CsvInput,
|
||||
|
||||
[string]$Username = "admin",
|
||||
|
||||
[string]$Password = ""
|
||||
)
|
||||
|
||||
# Performance : desactiver la barre de progression Invoke-WebRequest
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
# Import des modules
|
||||
$modulesPath = Join-Path $PSScriptRoot "modules"
|
||||
Import-Module (Join-Path $modulesPath "Logger.psm1") -Force
|
||||
Import-Module (Join-Path $modulesPath "CsvHandler.psm1") -Force
|
||||
Import-Module (Join-Path $modulesPath "ApiClient.psm1") -Force
|
||||
Import-Module (Join-Path $modulesPath "DaliParser.psm1") -Force
|
||||
|
||||
# Initialisation
|
||||
Initialize-Logger
|
||||
Initialize-ApiClient
|
||||
|
||||
Write-Log -Message "=== DaliACLI demarre - Action: $Action ===" -Level INFO
|
||||
|
||||
# Chemin de l'API DALI
|
||||
$daliApiPath = "/api/rest/v2/services/subnet/devices/light-sunblind/modules"
|
||||
|
||||
# Lecture du CSV d'entree
|
||||
$csvRows = Read-AutomateCsv -CsvPath $CsvInput
|
||||
|
||||
# ============================================================
|
||||
# ACTION READ : Lire la config DALI de chaque automate
|
||||
# ============================================================
|
||||
if ($Action -eq "Read") {
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd_HH\hmm"
|
||||
$CsvOutput = Join-Path (Get-Location) "dali_$timestamp.csv"
|
||||
Write-Log -Message "CSV de sortie : $CsvOutput" -Level INFO
|
||||
|
||||
$allOutputRows = @()
|
||||
|
||||
# Deduplication des automates par IP (le CSV d'entree a une ligne par automate)
|
||||
$uniqueAutomates = $csvRows | Sort-Object -Property "Current Ip" -Unique
|
||||
|
||||
foreach ($automate in $uniqueAutomates) {
|
||||
$hostname = $automate.Hostname
|
||||
$ip = $automate."Current Ip"
|
||||
|
||||
Update-Stats -Counter AutomatesTotal
|
||||
|
||||
try {
|
||||
$baseUrl = Get-BaseUrl -Automate $automate
|
||||
if (-not $baseUrl) {
|
||||
Write-Log -Message "[$hostname] Aucun port HTTP/HTTPS valide - ignore" -Level WARN
|
||||
Update-Stats -Counter AutomatesError
|
||||
continue
|
||||
}
|
||||
|
||||
$creds = Get-Credentials -Automate $automate -DefaultUsername $Username -DefaultPassword $Password
|
||||
$url = "$baseUrl$daliApiPath/"
|
||||
|
||||
Write-Log -Message "[$hostname] $url (user: $($creds.Username))" -Level INFO
|
||||
|
||||
# GET modules DALI
|
||||
$jsonContent = Invoke-ApiGet -Url $url -Username $creds.Username -Password $creds.Password
|
||||
|
||||
# Parser et filtrer les modules ECxLightDaliA
|
||||
$daliOutputs = Get-DaliAModules -JsonContent $jsonContent
|
||||
|
||||
if ($daliOutputs.Count -eq 0) {
|
||||
Write-Log -Message "[$hostname] Aucun module ECxLightDaliA trouve" -Level WARN
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Log -Message "[$hostname] $($daliOutputs.Count) sortie(s) ECxLightDaliA trouvee(s)" -Level INFO
|
||||
|
||||
# Creer une ligne CSV par output
|
||||
foreach ($output in $daliOutputs) {
|
||||
# Copier toutes les colonnes source de l'automate
|
||||
$row = [ordered]@{}
|
||||
foreach ($prop in $automate.PSObject.Properties) {
|
||||
$row[$prop.Name] = $prop.Value
|
||||
}
|
||||
# Ajouter les colonnes DALI
|
||||
$row["ModuleKey"] = $output.ModuleKey
|
||||
$row["ModuleName"] = $output.ModuleName
|
||||
$row["OutputKey"] = $output.OutputKey
|
||||
$row["OutputName"] = $output.OutputName
|
||||
$row["ControlGearKey"] = $output.ControlGearKey
|
||||
$row["Groups"] = $output.Groups
|
||||
$row["SystemFailLevel"] = $output.SystemFailLevel
|
||||
$row["PowerOnLevel"] = $output.PowerOnLevel
|
||||
$row["MinDimmingLevel"] = $output.MinDimmingLevel
|
||||
$row["DefaultValue"] = $output.DefaultValue
|
||||
$row["DimmingTime"] = $output.DimmingTime
|
||||
$row["MaxDimmingLevel"] = $output.MaxDimmingLevel
|
||||
|
||||
$allOutputRows += [PSCustomObject]$row
|
||||
Update-Stats -Counter OutputsProcessed
|
||||
|
||||
Write-Log -Message "[$hostname] M$($output.ModuleKey)_O$($output.OutputKey) ($($output.OutputName)) - Groups: $($output.Groups)" -Level SUCCESS
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log -Message "[$hostname] ERREUR : $($_.Exception.Message)" -Level ERROR
|
||||
Update-Stats -Counter AutomatesError
|
||||
}
|
||||
}
|
||||
|
||||
# Ecriture du CSV de sortie
|
||||
if ($allOutputRows.Count -gt 0) {
|
||||
Write-OutputCsv -OutputRows $allOutputRows -OutputPath $CsvOutput
|
||||
}
|
||||
else {
|
||||
Write-Log -Message "Aucune sortie trouvee - CSV non genere" -Level WARN
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# ACTION WRITE : Ecrire la config DALI sur chaque automate
|
||||
# ============================================================
|
||||
elseif ($Action -eq "Write") {
|
||||
# Grouper les lignes par automate (Current Ip)
|
||||
$automateGroups = $csvRows | Group-Object -Property "Current Ip"
|
||||
|
||||
foreach ($automateGroup in $automateGroups) {
|
||||
$ip = $automateGroup.Name
|
||||
$rows = $automateGroup.Group
|
||||
$hostname = $rows[0].Hostname
|
||||
|
||||
Update-Stats -Counter AutomatesTotal
|
||||
|
||||
try {
|
||||
$baseUrl = Get-BaseUrl -Automate $rows[0]
|
||||
if (-not $baseUrl) {
|
||||
Write-Log -Message "[$hostname] Aucun port HTTP/HTTPS valide - ignore" -Level WARN
|
||||
Update-Stats -Counter AutomatesError
|
||||
continue
|
||||
}
|
||||
|
||||
$creds = Get-Credentials -Automate $rows[0] -DefaultUsername $Username -DefaultPassword $Password
|
||||
$url = "$baseUrl$daliApiPath"
|
||||
|
||||
Write-Log -Message "[$hostname] $url (user: $($creds.Username))" -Level INFO
|
||||
|
||||
# Grouper par ModuleKey pour envoyer un POST par module
|
||||
$moduleGroups = $rows | Group-Object -Property ModuleKey
|
||||
|
||||
foreach ($moduleGroup in $moduleGroups) {
|
||||
$moduleKey = $moduleGroup.Name
|
||||
$outputRows = $moduleGroup.Group
|
||||
|
||||
Write-Log -Message "[$hostname] Module $moduleKey : $($outputRows.Count) sortie(s) a ecrire" -Level INFO
|
||||
|
||||
# Construire le body JSON
|
||||
$jsonBody = Build-ModuleWriteBody -ModuleKey $moduleKey -OutputRows $outputRows
|
||||
|
||||
Write-Log -Message "[$hostname] Module $moduleKey body: $jsonBody" -Level INFO
|
||||
|
||||
# POST vers l'API
|
||||
Invoke-ApiPost -Url $url -JsonBody $jsonBody -Username $creds.Username -Password $creds.Password
|
||||
|
||||
Update-Stats -Counter OutputsProcessed -Increment $outputRows.Count
|
||||
|
||||
Write-Log -Message "[$hostname] Module $moduleKey : configuration ecrite avec succes" -Level SUCCESS
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Log -Message "[$hostname] ERREUR : $($_.Exception.Message)" -Level ERROR
|
||||
Update-Stats -Counter AutomatesError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Resume final
|
||||
Write-Summary
|
||||
Reference in New Issue
Block a user