# Module ApiClient - Communication REST API Eclypse function Initialize-ApiClient { [CmdletBinding()] param() # Forcer TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Desactiver la verification SSL (certificats auto-signes) if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) { Add-Type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ } [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy Write-Log -Message "ApiClient initialise (TLS 1.2, SSL bypass)" -Level INFO } function Get-AuthHeader { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Username, [Parameter(Mandatory)] [AllowEmptyString()] [string]$Password ) $pair = "${Username}:${Password}" $bytes = [System.Text.Encoding]::ASCII.GetBytes($pair) $base64 = [System.Convert]::ToBase64String($bytes) return @{ "Authorization" = "Basic $base64" "Accept" = "application/json, text/json, text/x-json, text/javascript, application/xml, text/xml, text/plain" "User-Agent" = "EC-gfxProgram/7.9.26006.1 (DC_API:v1; Win32NT 6.2)" } } function Invoke-EnoceanGet { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$BaseUrl, [Parameter(Mandatory)] [string]$ApiBasePath, [Parameter(Mandatory)] [string]$ResourcePath, [Parameter(Mandatory)] [string]$Username, [Parameter(Mandatory)] [AllowEmptyString()] [string]$Password ) $headers = Get-AuthHeader -Username $Username -Password $Password $url = "$BaseUrl$ApiBasePath/$($ResourcePath.TrimStart('/'))" Write-Log -Message "GET $url" -Level INFO $response = Invoke-WebRequest -Uri $url -Method GET -Headers $headers -UseBasicParsing -TimeoutSec 30 # Si la reponse est un byte[] (encode=bin), decoder en string UTF-8 sans BOM if ($response.Content -is [byte[]]) { return [System.Text.Encoding]::UTF8.GetString($response.Content).TrimStart([char]0xFEFF) } return $response.Content } function Send-EnoceanConfig { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$BaseUrl, [Parameter(Mandatory)] [string]$ApiBasePath, [Parameter(Mandatory)] [byte[]]$ZipBytes, [Parameter(Mandatory)] [string]$ZipFilename, [Parameter(Mandatory)] [string]$Username, [Parameter(Mandatory)] [AllowEmptyString()] [string]$Password ) $authHeaders = Get-AuthHeader -Username $Username -Password $Password $url = "$BaseUrl$ApiBasePath/files/bacnet/inputConfiguration" Write-Log -Message "POST $url (fichier: $ZipFilename, taille: $($ZipBytes.Length) octets)" -Level INFO # Construction multipart manuelle $boundary = [System.Guid]::NewGuid().ToString("N") $encoding = [System.Text.Encoding]::ASCII # Partie avant le fichier $headerPart = "--$boundary`r`nContent-Disposition: form-data; name=`"File`"; filename=`"$ZipFilename`"`r`nContent-Type: application/octet-stream`r`n`r`n" # Partie finale $footerPart = "`r`n--$boundary--`r`n" $headerBytes = $encoding.GetBytes($headerPart) $footerBytes = $encoding.GetBytes($footerPart) # Assembler le body complet en byte[] $bodyStream = New-Object System.IO.MemoryStream $bodyStream.Write($headerBytes, 0, $headerBytes.Length) $bodyStream.Write($ZipBytes, 0, $ZipBytes.Length) $bodyStream.Write($footerBytes, 0, $footerBytes.Length) $bodyBytes = $bodyStream.ToArray() $bodyStream.Close() # Utiliser HttpWebRequest directement pour envoyer les bytes bruts sans troncature $request = [System.Net.HttpWebRequest]::Create($url) $request.Method = "POST" $request.ContentType = "multipart/form-data; boundary=$boundary" $request.ContentLength = $bodyBytes.Length $request.Timeout = 60000 $request.UserAgent = $authHeaders["User-Agent"] $request.Accept = $authHeaders["Accept"] $request.Headers.Add("Authorization", $authHeaders["Authorization"]) try { $reqStream = $request.GetRequestStream() $reqStream.Write($bodyBytes, 0, $bodyBytes.Length) $reqStream.Close() $response = $request.GetResponse() $statusCode = [int]$response.StatusCode $response.Close() Write-Log -Message "POST reponse : $statusCode" -Level SUCCESS } catch [System.Net.WebException] { $responseBody = "" if ($_.Exception.Response) { $stream = $_.Exception.Response.GetResponseStream() $reader = New-Object System.IO.StreamReader($stream) $responseBody = $reader.ReadToEnd() $reader.Close() $stream.Close() } Write-Log -Message "POST erreur $($_.Exception.Message) - Reponse serveur: $responseBody" -Level ERROR throw } } Export-ModuleMember -Function Initialize-ApiClient, Get-AuthHeader, Invoke-EnoceanGet, Send-EnoceanConfig