NTP-Server setzen bie Tasmota-Geräten per Powershell

# One-Shot: Setzt NTP-Server bei allen Sonoff/Tasmota-Geräten im Netz 10.50.5.0/24
# PowerShell 5.1 kompatibel

$subnet         = "192.168.5"
$ntp1           = "192.168.4.250"
$ntp2           = "192.168.4.251"
$ntp3           = "ptbtime1.ptb.de"   # leer zulässig
$httpTimeoutSec = 2                   # schneller als vorher
$pingTimeoutMs  = 150                 # sehr schneller Erreichbarkeits-Check

# Optional: Web-Auth
$user = ""
$pass = ""

# ---------- Helper ----------
function Test-QuickPing {
    param([string]$Ip, [int]$TimeoutMs = 150)
    try {
        $p = New-Object System.Net.NetworkInformation.Ping
        $r = $p.Send($Ip, $TimeoutMs)
        return ($r.Status -eq [System.Net.NetworkInformation.IPStatus]::Success)
    } catch {
        return $false
    }
}

$results = @()
Write-Host "🔎 Scanne $subnet.1–254 (Ping-Timeout ${pingTimeoutMs}ms, HTTP-Timeout ${httpTimeoutSec}s)..." -ForegroundColor Cyan

for ($h = 1; $h -le 254; $h++) {
    $ip = "$subnet.$h"

    # Fortschritt + aktuelle IP anzeigen
    $pct = [math]::Round(($h/254)*100, 0)
    Write-Progress -Activity "Netz-Scan" -Status "Prüfe $ip" -PercentComplete $pct

    # optional zusätzlich in die Konsole schreiben (kommentieren wenn zu „laut“)
    if ($h % 16 -eq 1) { Write-Host "➡️  Aktuell: $ip" }

    # 1) Ultraschneller Reachability-Check
    if (-not (Test-QuickPing -Ip $ip -TimeoutMs $pingTimeoutMs)) {
        $results += [pscustomobject]@{ IP=$ip; IsTasmota=$null; Action="skip"; Detail="kein Ping" }
        continue
    }

    try {
        # 2) Tasmota-Erkennung
        $probeCmd = [uri]::EscapeDataString("Status 0")
        $authPart = ""
        if ($user -and $pass) {
            $authPart = "&user=$([uri]::EscapeDataString($user))&password=$([uri]::EscapeDataString($pass))"
        }
        $probeUrl = "http://$ip/cm?cmnd=$probeCmd$authPart"

        $resp = Invoke-WebRequest -Uri $probeUrl -TimeoutSec $httpTimeoutSec -UseBasicParsing -ErrorAction Stop
        $isTasmota = ($resp.Content -match 'Tasmota' -or $resp.Content -match '"StatusFWR"' -or $resp.Content -match '"Module":"Sonoff')

        if (-not $isTasmota) {
            $results += [pscustomobject]@{ IP=$ip; IsTasmota=$false; Action="skip"; Detail="kein Tasmota" }
            continue
        }

        # 3) NTP setzen (Backlog). Wenn $ntp3 leer ist, ist das ok.
        $cmdParts = @("NtpServer1 $ntp1","NtpServer2 $ntp2")
        if ($ntp3 -ne "") { $cmdParts += "NtpServer3 $ntp3" }
        $cmd = "Backlog " + ($cmdParts -join ";")

        $encoded = [uri]::EscapeDataString($cmd)
        $url = "http://$ip/cm?cmnd=$encoded$authPart"

        $setResp = Invoke-WebRequest -Uri $url -TimeoutSec $httpTimeoutSec -UseBasicParsing -ErrorAction Stop
        $ok = ($setResp.StatusCode -eq 200)
        $detail = if ($ok) { "NTP gesetzt" } else { "HTTP $($setResp.StatusCode)" }

        $results += [pscustomobject]@{ IP=$ip; IsTasmota=$true; Action="set-ntp"; Detail=$detail }
    }
    catch {
        $results += [pscustomobject]@{ IP=$ip; IsTasmota=$null; Action="error"; Detail=$_.Exception.Message }
    }
}

Write-Progress -Activity "Netz-Scan" -Completed
$results | Sort-Object IP | Format-Table -AutoSize
Write-Host "✅ Fertig." -ForegroundColor Green