Untitled

Anonymous
plain_text
01/16/2026 7:12 PM
13.8 KB
9
Indexable
# CheckBusStops.ps1 - 90min GREEN | >90min RED | Never RED (REFACTORED)
#
# Usage: .\CheckBusStops.ps1
# Features: [Green] OK:<90min | [Red] SLOW:>90min | [Red] OFFLINE:Never
#

param(
    [int]$MinutesGreen = 90,    # GREEN: <90min
    [int]$HoursInactive = 360   # RED: >6h (backup check)
)

Write-Host "FULL BITA Log Monitor (86 stops)..." -ForegroundColor Cyan

$BITALogsPath = "E:\OPT\IMS\Opt.IMS.BITA.Webservice\Logs"

# FULL MAPPING - ID → Stop Name (86 stops) - UNCHANGED
$BusStops = @{
    "A10" = "Rua do Outeiro"; "A11" = "Rua de Mocambique"; "A12" = "Rua do Sobreiral"
    "A13" = "Rua Afonso Henriques 1"; "A14" = "Rua Afonso Henriques 2"; "A15" = "Rua Afonso Henriques 3"
    "A16" = "Rua Afonso Henriques 4"; "A17" = "Rua Afonso Henriques 5"; "A18" = "Rua Alexandre Herculano"
    "A19" = "Av. Eng. Arantes de Oliveira1"; "A2" = "Rua Comendador Rainho"; "A20" = "Av. Eng. Arantes de Oliveira 2"
    "A21" = "Rua Oliveira Junior 1"; "A22" = "Rua Oliveira Junior 2"; "A23" = "Rua Oliveira Junior 3"
    "A24" = "Rua Serpa Pinto"; "A25" = "Rua Guerra Junqueiro"; "A27" = "Rua Dr. Serafim Leite"
    "A28_" = "Rua Antonio Silva"; "A29" = "Rua Afonso de Albuquerque"; "A3" = "Av. Dr. Renato Araujo 3"
    "A30" = "Rua dos Ribeiros"; "A31" = "Rua do Vale 1"; "A32" = "Rua do Vale 2"
    "A33" = "Rua Domingos Jose de Oliveira"; "A34" = "Rua Manuel Pais Vieira Junior"
    "A35" = "Rua das Travessas"; "A36" = "Rua do Espadanal"; "A37" = "Rua Banda da Musica"
    "A38" = "Av. da Liberdade"; "A39" = "Rua Adelino Amaro da Costa"; "A40" = "Rua da Restauracao"
    "A41" = "Rua Bairro do Hospital"; "A42" = "Rua Dr. Adolfo Coutinho 1"; "A43" = "Rua Dr. Adolfo Coutinho 2"
    "A44" = "Rua Visconde 1"; "A45" = "Rua Visconde 2"; "A47" = "Praca Luis Ribeiro"
    "A48" = "Av. da Liberdade 2"; "A5" = "Rua dos Bombeiros Voluntarios"; "A6" = "Praca Barbazieux"
    "A7" = "Av. do Brasil"; "A8" = "Rua Antonio Nicolau da Costa"; "A9" = "Av. de Casaldelo"
    "V0-A0" = "Centro Coordenador de Transportes"; "V10" = "Bairro do Orreiro"; "V11" = "Rua Vale do Vouga"
    "V12" = "Rua Manuel Luis da Costa Esc Serafim Leite"; "V13" = "Av. da Misericordia"
    "V14" = "Av. Dr. Renato Araujo 1"; "V15-A46" = "Rua Joao de Deus"; "V16" = "Av. Benjamim Araujo"
    "V17" = "Rua Aloa de Morais"; "V18" = "Largo de S. Joao"; "V19" = "Rua Antonio Henriques"
    "V1-A1" = "Av. Dr Renato Araujo 1"; "V20" = "Rua Jose Soares da Silva 1"; "V21" = "Rua Jose Soares da Silva 2"
    "V22" = "Rua da Mourisca Esc. Joao da Silva Correia - CERCI"; "V23" = "Rua da Mourisca"
    "V24" = "Rua das Aguas 1"; "V25" = "Rua das Aguas 2"; "V26" = "Av.a 1. de Maio"
    "V27" = "Rua dos Acores"; "V28" = "Rua Manuel Vieira Araujo"; "V29" = "Rua Grupo Patriotico Sanjoanense"
    "V2-A4" = "Av. da Misericordia"; "V30" = "Rua Milheiros de Poiares"; "V31" = "Rua do Parrinho 1"
    "V32" = "Rua do Parrinho 2"; "V33" = "Rua da Mourisca"; "V34" = "Rua da Mourisca Esc. Joao da Silva Correia - CERCI"
    "V35" = "Rua Jose Soares da Silva 2"; "V36" = "Rua Jose Soares da Silva 1"; "V37" = "Rua Antonio Henriques"
    "V38" = "Largo de S. Joao"; "V39-A26" = "Rua Aloa de Morais"; "V40" = "Av. Benjamim Araujo"
    "V41" = "Rua Joao de Deus"; "V3" = "Rua Manuel Luis da Costa Esc Serafim Leite"
    "V4" = "Rua do Vale do Vouga"; "V5" = "Rua Cerqueira de Vasconcelos"; "V6" = "Rua Manuel Luis Leite Junior"
    "V7" = "Av. Dr. Renato Araujo 2"; "V8" = "Rua de Cucujaes"; "V9" = "Rua Bartolomeu Dias ZI Orreiro"
}

# Get today's BITA log
$bitaFiles = Get-ChildItem -Path $BITALogsPath -Filter "BITA_Log.txt*" | Where-Object { $_.LastWriteTime.Date -eq (Get-Date).Date }
$bitaLog = if ($bitaFiles) { ($bitaFiles | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName } else { $null }

if (-not $bitaLog) {
    Write-Host "No BITA log found for today!" -ForegroundColor Red
    exit
}

$fileSize = (Get-Item $bitaLog).Length / 1KB
Write-Host "BITA Log: $bitaLog ($([math]::Round($fileSize,1)) KB)" -ForegroundColor Green

$Now = Get-Date
$GreenThreshold = $Now.AddMinutes(-$MinutesGreen)  # 90min threshold

Write-Host "Scanning $($BusStops.Count) stops..." -ForegroundColor Yellow

$results = @()
$counter = 0
foreach ($stopId in $BusStops.Keys) {
    $counter++
    $stopName = $BusStops[$stopId]
    Write-Progress -Activity "Scanning BITA Log" -Status "$counter/$($BusStops.Count): $stopId" -PercentComplete (($counter/$BusStops.Count)*100)
    
    $latestActivity = $null
    
    # Search for this exact stop name in BITA log
    $stopPattern = "Stop:\s*" + [regex]::Escape($stopName)
    $stopLines = Select-String -Path $bitaLog -Pattern $stopPattern -Quiet
    
    if ($stopLines) {
        $allStopLines = Select-String -Path $bitaLog -Pattern $stopPattern
        foreach ($line in $allStopLines) {
            if ($line.Line -match "^(\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2})") {
                try {
                    $timestamp = [DateTime]::ParseExact($matches[1], "yyyy-MM-dd HH:mm:ss", $null)
                    if (-not $latestActivity -or $timestamp -gt $latestActivity) {
                        $latestActivity = $timestamp
                    }
                }
                catch {}
            }
        }
    }
    
    # NEW 90min LOGIC: GREEN <90min | RED >90min | RED Never
    if (-not $latestActivity) {
        $status = '[Red] OFFLINE'
        $ageMinutes = 99999
    }
    elseif ($latestActivity -gt $GreenThreshold) {
        $status = '[Green] OK'
        $ageMinutes = [math]::Round(($Now - $latestActivity).TotalMinutes)
    }
    else {
        $status = '[Red] SLOW'
        $ageMinutes = [math]::Round(($Now - $latestActivity).TotalMinutes)
    }
    
    $results += [PSCustomObject]@{
        ID = $stopId
        Name = $stopName
        Status = $status
        LastSeen = if ($latestActivity) { $latestActivity.ToString("HH:mm:ss") } else { "Never" }
        AgeMinutes = $ageMinutes
    }
}

Write-Progress -Activity "Scanning BITA Log" -Completed

# SORT BY STATUS: Green first, then Red (SLOW), then Red (OFFLINE)
$results = $results | Sort-Object { 
    switch ($_.Status) {
        '[Green] OK' { 0 }
        '[Red] SLOW' { 1 }
        '[Red] OFFLINE' { 2 }
    }
}, AgeMinutes

Clear-Host
$currentTime = Get-Date -Format "HH:mm:ss"
Write-Host "=== BITA LOG MONITORING (86 STOPS) - $currentTime ===" -ForegroundColor Cyan
Write-Host "[Green] OK:<90min | [Red] SLOW:>90min | [Red] OFFLINE:Never`n" -ForegroundColor White

$green = ($results | Where-Object Status -eq '[Green] OK').Count
$redSlow = ($results | Where-Object Status -eq '[Red] SLOW').Count
$redOffline = ($results | Where-Object Status -eq '[Red] OFFLINE').Count
Write-Host "SUMMARY: [Green] $green | [Red] SLOW:$redSlow | [Red] OFFLINE:$redOffline (Total: $($results.Count))" -ForegroundColor Yellow

# GREEN STOPS FIRST (sorted by AgeMinutes)
$greenStops = $results | Where-Object Status -eq '[Green] OK'
if ($greenStops) {
	Write-Host "`nGREEN STOPS (-90min):" -ForegroundColor Green
	Write-Host "ID   Name                          Status    LastSeen  Age" -ForegroundColor Green
    Write-Host "---- --------------------------- --------- --------- ----" -ForegroundColor Green
    $greenStops | Format-Table ID,Name,Status,LastSeen,@{Name='Age';Expression={[math]::Round($_.AgeMinutes)}} -AutoSize -Wrap
    Write-Host "`n"
}

# YELLOW SLOW STOPS (+90min)
$redSlowStops = $results | Where-Object Status -eq '[Yellow] SLOW'
if ($redSlowStops) {
    Write-Host "YELLOW SLOW STOPS (+90min):" -ForegroundColor Red
    Write-Host "ID      Name                                            Status    LastSeen  Age" -ForegroundColor Yellow
    Write-Host "-------- --------------------------------------------- --------- --------- ----" -ForegroundColor Yellow
    $redSlowStops | Format-Table ID,Name,Status,LastSeen,@{Name='Age';Expression={[math]::Round($_.AgeMinutes)}} -AutoSize -Wrap
    Write-Host "`n"
}

# RED OFFLINE STOPS (Never)
$redOfflineStops = $results | Where-Object Status -eq '[Red] OFFLINE'
if ($redOfflineStops) {
    Write-Host "RED OFFLINE STOPS (Never):" -ForegroundColor Red
    Write-Host "ID      Name                                            Status        LastSeen" -ForegroundColor Red
    Write-Host "-------- --------------------------------------------- ------------- --------" -ForegroundColor Red
    $redOfflineStops | Format-Table ID,Name,Status,LastSeen -AutoSize -Wrap
}

$csvName = "BITA_BusStops_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$results | Export-Csv -Path $csvName -NoTypeInformation
Write-Host "`nCSV: $csvName" -ForegroundColor Green
Write-Host "COMPLETE!" -ForegroundColor Green

# ==== EMAIL REPORT - SECURE CREDENTIAL ====
$Now = Get-Date
$smtpServer   = "outlook.office365.com"
$smtpPort     = 587
$smtpFrom     = "[email protected]"
$smtpFromName = "SJ Madeira - BUS Stops LED"
$to           = "[email protected]"

$credPath = "E:\OPT\IMS\smtp-cred.xml"
if (-not (Test-Path $credPath)) {
    Write-Host "Create credential first:" -ForegroundColor Yellow
    Write-Host "  `$cred = Get-Credential -UserName '[email protected]'" -ForegroundColor Yellow
    Write-Host "  `$cred | Export-Clixml 'E:\OPT\IMS\smtp-cred.xml'" -ForegroundColor Yellow
    exit
}
$cred = Import-Clixml $credPath

$csvFullPath = Join-Path (Get-Location) $csvName
if (-not (Test-Path $csvFullPath)) {
    Write-Host "CSV not found: $csvFullPath" -ForegroundColor Red
    exit
}

$subject = "Bus stops LED status - $($Now.ToString('yyyy-MM-dd HH:mm')) - Green:$green Red:$($redSlow+$redOffline)"
$body    = "Bom dia,`r`n`r`nRelatorio BITA_Log em anexo.`r`n`r`nGreen: $green | Red Slow: $redSlow | Red Offline: $redOffline`r`n`r`nCumprimentos,"

$mail = New-Object System.Net.Mail.MailMessage($smtpFrom, $to, $subject, $body)
$mail.From = New-Object System.Net.Mail.MailAddress($smtpFrom, $smtpFromName)
$attachment = New-Object Net.Mail.Attachment($csvFullPath)
$mail.Attachments.Add($attachment)

$smtpClient = New-Object Net.Mail.SmtpClient($smtpServer, $smtpPort)
$smtpClient.EnableSsl = $true
$smtpClient.Credentials = $cred

try {
    Write-Host "Sending email to $to..." -ForegroundColor Cyan
    $smtpClient.Send($mail)
    Write-Host "Email sent OK!" -ForegroundColor Green
}
catch {
    $errorMsg = $_.Exception.Message
    Write-Host "Email FAILED: $errorMsg" -ForegroundColor Red
}
finally {
    $mail.Dispose()
    $attachment.Dispose()
}

Editor is loading...
Leave a Comment