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