For our example, we are parsing Milestone’s configuration file using PowerShell to build a weekly report. Ideally, you would leverage a fully-featured monitor like SolarWinds or AppManager to monitor Milestone devices and alert based on a defined threshold, but for some this may not be possible. Still, if needed, you could leverage PowerShell to parse the configurattion.xml file.
Our example does the following:
- Import MileStone configuration.xml file
- Parse configuration file for devices (JSON format).
- Attempts to ping the firewall based on the camera’s subnet
- if the camera is offline, it adds the camera to a report object
- if the camera is online – do nothing.
- Determine if a report needs to be sent:
- if the report object has any items within it, then we want to send out a notification with the camera information for follow up.
- If there is nothing in the report – do nothing.
Looking back, I would utilize functions to make the script modular and convert write-host to write-debug which I could then leverage to toggle data to the host during debugging.
On a side note: While writing this post I found that MileStone has released a PSModule which allows for further integration: https://supportcommunity.milestonesys.com/s/article/How-To-Use-MilestonePSTools-PowerShell-Module?language=en_US
# Email Report $From = "[email protected]" $To = "[email protected]" $Cc = "[email protected]" $Subject = (Get-Date).ToString("%d-MMMM-yyyy") + " - Weekly Report - Offline Cameras" $SMTPServer = "mail.domain.com" # Define HTML Report Header Style $Header = @" <style> body { font-size:12px; font-family:Verdana, Geneva, sans-serif;} TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;} TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #e5efff;} TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;} tr:nth-child(even) {background: #ededed} tr:nth-child(odd) {background: #FFF} </style> "@ # Import Milestone Config $xmlLocation = 'C:\ProgramData\Milestone\Milestone Surveillance\configuration.xml' $deviceObjs = Select-Xml -Path $xmlLocation -XPath "//config/Devices/node()" | Select-Object -ExpandProperty node | Where-Object { $_.Name -ne '#whitespace' } # Declare Report $report = @() # Go through each device, test, and report on offline cameras foreach ($device in $deviceObjs) { Write-Host "Testing $($device.DisplayName)" # Test points - Camera and Firewall $camTestResult = (Test-NetConnection $device.IPAddress -Port 80 -ErrorAction SilentlyContinue -WarningAction SilentlyContinue).TcpTestSucceeded $gwTestResult = (Test-NetConnection $($device.IPAddress -replace "\.\d{1,3}$", ".1") -ErrorAction SilentlyContinue -WarningAction SilentlyContinue).PingSucceeded # Check Status if ($camTestResult -eq $true) { Write-Host -ForegroundColor Green " Status: Online" } if (($camTestResult -eq $false) -and ($gwTestResult -eq $true)) { # Debug Status Write-Host -ForegroundColor Red " Firewall Status: $gwTestResult" Write-Host -ForegroundColor Red " Camera Status: $camTestResult" # Add to Report $item = New-Object PSObject $item | Add-Member -type NoteProperty -Name 'Camera Name' -Value $($device.DisplayName) $item | Add-Member -type NoteProperty -Name 'Camera IP' -Value $($device.IPAddress) $item | Add-Member -type NoteProperty -Name 'Online' -Value $($camTestResult) $report += $item } elseif (($camTestResult -eq $false) -and ($gwTestResult -eq $false)) { Write-Host 'Status: Tunnel Down' } } if ($report) { $HTMLReport = $report | Sort-Object 'Camera Name' | ConvertTo-Html -property 'Camera Name', 'Camera IP', 'Online' -Head $Header -Pre "<h2>Property Weekly Report - Offline MDF Cameras</h2><p><b>Generated:</b> $(get-date)</p>" Send-MailMessage -To $To -Cc $Cc -From $From -SmtpServer $SMTPServer -Subject $Subject -Body ($HTMLReport | Out-String) -BodyAsHtml }