Skip to content

Instantly share code, notes, and snippets.

@joshooaj
Created September 11, 2020 00:04
Show Gist options
  • Save joshooaj/99c86be94a4a983ff4fd2b74bf175874 to your computer and use it in GitHub Desktop.
Save joshooaj/99c86be94a4a983ff4fd2b74bf175874 to your computer and use it in GitHub Desktop.
A couple of functions to import Oregon and Washington DOT traffic cameras with GPS coordinates into Milestone
function Import-TripCheck {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[VideoOS.Platform.ConfigurationItems.RecordingServer]
$Recorder,
[Parameter(Mandatory)]
[string]
$ApiKey,
[Parameter()]
[string]
$CameraGroupBasePath = "/TripCheck/",
# A bug in Universal Driver means cameras with spaces in the ConnectionURI won't work. You should include this parameter until it's fixed.
[Parameter()]
[switch]
$IgnoreCamerasWithSpaces,
[Parameter()]
[ValidateSet(1, 16, 64, 512)]
[int]
$CameraCount = 512
)
begin {
$drivers = @{
1 = 412
16 = 409
64 = 410
512 = 411
}
}
process {
$ErrorActionPreference = "Stop"
try {
if (!$CameraGroupBasePath.EndsWith("/")) {
$CameraGroupBasePath = $CameraGroupBasePath + "/"
}
$response = Invoke-RestMethod -Method Get -Uri https://api.odot.state.or.us/tripcheck/Cctv/Inventory -UseBasicParsing -Headers @{'Ocp-Apim-Subscription-Key' = $ApiKey}
$response.CCTVInventoryRequest | ForEach-Object {
$_.'last-update-time' = [datetime]::Parse($_.'last-update-time')
}
$cctvCameras = $response.CCTVInventoryRequest | Sort-Object 'last-update-time' -Descending
if ($IgnoreCamerasWithSpaces) {
$cctvCameras = $cctvCameras | Where-Object { !$_.'cctv-url'.Contains(" ") -and !$_.'cctv-url'.Contains("%20") }
}
# Create device groups by route-id
$cctvCameras | Group-Object 'route-id' | ForEach-Object {
$null = Add-DeviceGroup -DeviceCategory Camera -Path ($CameraGroupBasePath + $_.Name)
}
# Enable hardware, set name, and enable HTTPS
$hardware = $Recorder | Add-Hardware -Address "www.tripcheck.com" -UseDefaultCredentials -DriverId $drivers[$CameraCount] -GroupPath $CameraGroupBasePath
$hardware.Name = "TripCheck"
$hardware.Enabled = $true
$hardware | Set-HardwareSetting -Name HTTPSEnabled -Value Yes
$hardware.Save()
# Configure camera channels
$cameraItems = Get-ConfigurationItem -Path "Hardware[$($hardware.Id)]/CameraFolder" -ChildItems | Sort-Object { [int]($_.Properties | ? Key -eq 'Channel').Value }
Write-Progress -Id 0 -Activity "Configuring cameras" -PercentComplete 0
foreach ($index in 0..($cctvCameras.Count-1)) {
if ($index -ge $CameraCount) {
Write-Warning "Universal Driver with 512 channels is now full - the remaining ODOT cameras will not be added"
break
}
# Hacky workaround to try to ensure the config api client doesn't timeout
if ($index % 10 -eq 0) {
Select-Site -MasterSite
}
$cctvCamera = $cctvCameras[$index]
$item = $cameraItems[$index]
$uri = [uri]$cctvCamera.'cctv-url'
Write-Progress -Id 0 -Activity "Configuring cameras" -Status "Configuring $($cctvCamera.'cctv-other') on channel $index" -PercentComplete ([int]( $index / ( $cctvCameras.Count-1 ) * 100))
$item.EnableProperty.Enabled = $true
($item.Properties | Where-Object Key -eq 'Name').Value = $cctvCamera.'cctv-other'
($item.Properties | Where-Object Key -eq 'ShortName').Value = $cctvCamera.'device-id'
($item.Properties | Where-Object Key -eq 'Description').Value = "$($cctvCamera.'route-id') milepoint $($cctvCamera.milepoint)"
($item.Properties | Where-Object Key -eq 'GisPoint').Value = "POINT ($($cctvCamera.longitude) $($cctvCamera.latitude))"
$null = $item | Set-ConfigurationItem
$driverSettings = Get-ConfigurationItem -Path "DeviceDriverSettings[$(($item.Properties | Where-Object Key -eq Id).Value)]"
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*DeliveryMode*').Value = 'Non Multipart Stream'
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*KeepAliveType*').Value = 'NEVER'
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*RetrievalMode*').Value = 'Snapshot'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*Codec*').Value = 'jpeg'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*FPS*').Value = '.1'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*StreamingMode*').Value = 'HTTP'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*ConnectionURI*').Value = $uri.PathAndQuery.TrimStart(@('/'))
$null = $driverSettings | Set-ConfigurationItem
Add-DeviceGroupMember -DeviceCategory Camera -Path ($CameraGroupBasePath + $cctvCamera.'route-id') -DeviceId ($item.Properties | Where-Object Key -eq Id).Value
}
Write-Progress -Id 0 -Activity "Configuring cameras" -PercentComplete 100 -Completed
}
catch {
if ($null -ne $hardware) {
try { $hardware | Remove-Hardware -Force } catch {}
}
throw
}
finally {
$ErrorActionPreference = "Continue"
}
}
}
function Import-WSDOT {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[VideoOS.Platform.ConfigurationItems.RecordingServer]
$Recorder,
[Parameter(Mandatory)]
[string]
$ApiKey,
[Parameter()]
[string]
$CameraGroupBasePath = "/WSDOT/",
# A bug in Universal Driver means cameras with spaces in the ConnectionURI won't work. You should include this parameter until it's fixed.
[Parameter()]
[switch]
$IgnoreCamerasWithSpaces,
[Parameter()]
[ValidateSet(1, 16, 64, 512)]
[int]
$CameraCount = 64
)
begin {
$drivers = @{
1 = 412
16 = 409
64 = 410
512 = 411
}
}
process {
$ErrorActionPreference = "Stop"
try {
if (!$CameraGroupBasePath.EndsWith("/")) {
$CameraGroupBasePath = $CameraGroupBasePath + "/"
}
$cctvCameras = Invoke-RestMethod -Method Get -Uri "http://www.wsdot.com/Traffic/api/HighwayCameras/HighwayCamerasREST.svc/SearchCamerasAsJson?AccessCode=$($ApiKey)" -UseBasicParsing
if ($IgnoreCamerasWithSpaces) {
$cctvCameras = $cctvCameras | Where-Object { !$_.ImageURL.Contains(" ") -and !$_.ImageURL.Contains("%20") }
}
# Create device groups by CameraLocation.RoadName
$cctvCameras | Group-Object { $_.CameraLocation.RoadName } | ForEach-Object {
$null = Add-DeviceGroup -DeviceCategory Camera -Path ($CameraGroupBasePath + $_.Name)
}
# Enable hardware, set name, and enable HTTPS
$hardware = $Recorder | Add-Hardware -Address "images.wsdot.wa.gov" -UseDefaultCredentials -DriverId $drivers[$CameraCount] -GroupPath $CameraGroupBasePath
$hardware.Name = "WSDOT"
$hardware.Enabled = $true
$hardware | Set-HardwareSetting -Name HTTPSEnabled -Value Yes
$hardware.Save()
# Configure camera channels
$cameraItems = Get-ConfigurationItem -Path "Hardware[$($hardware.Id)]/CameraFolder" -ChildItems | Sort-Object { [int]($_.Properties | ? Key -eq 'Channel').Value }
Write-Progress -Id 0 -Activity "Configuring cameras" -PercentComplete 0
foreach ($index in 0..($cctvCameras.Count-1)) {
if ($index -ge $CameraCount) {
Write-Warning "Universal Driver with 64 channels is now full - the remaining WSDOT cameras will not be added"
break
}
# Hacky workaround to try to ensure the config api client doesn't timeout
if ($index % 10 -eq 0) {
Select-Site -MasterSite
}
$cctvCamera = $cctvCameras[$index]
$item = $cameraItems[$index]
$uri = [uri]$cctvCamera.ImageURL
Write-Progress -Id 0 -Activity "Configuring cameras" -Status "Configuring $($cctvCamera.Title) on channel $index" -PercentComplete ([int]( $index / ( $cctvCameras.Count-1 ) * 100))
$item.EnableProperty.Enabled = $true
($item.Properties | Where-Object Key -eq 'Name').Value = $cctvCamera.Title
($item.Properties | Where-Object Key -eq 'ShortName').Value = $cctvCamera.CameraID
($item.Properties | Where-Object Key -eq 'Description').Value = $cctvCamera | ConvertTo-Json
($item.Properties | Where-Object Key -eq 'GisPoint').Value = "POINT ($($cctvCamera.DisplayLongitude) $($cctvCamera.DisplayLatitude))"
$null = $item | Set-ConfigurationItem
$driverSettings = Get-ConfigurationItem -Path "DeviceDriverSettings[$(($item.Properties | Where-Object Key -eq Id).Value)]"
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*DeliveryMode*').Value = 'Non Multipart Stream'
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*KeepAliveType*').Value = 'NEVER'
(($driverSettings.Children | Where-Object DisplayName -eq General).Properties | Where-Object Key -like '*RetrievalMode*').Value = 'Snapshot'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*Codec*').Value = 'jpeg'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*FPS*').Value = '.1'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*StreamingMode*').Value = 'HTTP'
(($driverSettings.Children | Where-Object DisplayName -eq 'Video stream 1').Properties | Where-Object Key -like '*ConnectionURI*').Value = $uri.PathAndQuery.TrimStart(@('/'))
$null = $driverSettings | Set-ConfigurationItem
Add-DeviceGroupMember -DeviceCategory Camera -Path ($CameraGroupBasePath + $cctvCamera.CameraLocation.RoadName) -DeviceId ($item.Properties | Where-Object Key -eq Id).Value
}
Write-Progress -Id 0 -Activity "Configuring cameras" -PercentComplete 100 -Completed
}
catch {
if ($null -ne $hardware) {
try { $hardware | Remove-Hardware -Force } catch {}
}
throw
}
finally {
$ErrorActionPreference = "Continue"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment