Skip to content

Instantly share code, notes, and snippets.

@joshooaj
Last active June 17, 2021 15:30
Show Gist options
  • Select an option

  • Save joshooaj/a4f3d38bec9e1f0166a9c6b31fd7b65b to your computer and use it in GitHub Desktop.

Select an option

Save joshooaj/a4f3d38bec9e1f0166a9c6b31fd7b65b to your computer and use it in GitHub Desktop.
Exports the GPS coordinates of all cameras from a Milestone XProtect VMS installation
# Make sure we have permission to execute ps1 files within the scope of this running process only
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force -Confirm:$false
if ($null -eq (Get-Module -ListAvailable -Name MilestonePSTools)) {
# MilestonePSTools is not installed so let's take care of some prerequisits for using Install-Module to install it
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
$nugetProvider = Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction Ignore
if ($null -eq $nugetProvider -or $nugetProvider.Version -lt [version]'2.8.5.201') {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
}
$psgetModule = Get-Module -ListAvailable -Name PowerShellGet -ErrorAction Ignore
if ($null -eq $psgetModule -or $psgetModule.Version -lt [version]'2.2.5') {
Install-Module PowerShellGet -MinimumVersion 2.2.5 -Force -Confirm:$false
}
# Now we install MilestonePSTools and by extension, MipSdkRedist
Install-Module MilestonePSTools -Force -Confirm:$false
}
# Prompt for Milestone VMS login information and continue to prompt until we are successfully connected
while ($null -eq (Get-ManagementServer -ErrorAction Ignore)) {
$server = Read-Host -Prompt "Milestone VMS server address"
$credential = Get-Credential -Message "Milestone VMS user"
$basic = "y" -eq (Read-Host -Prompt "Is this a basic user (y/n)?")
Connect-ManagementServer -Server $server -Credential $credential -BasicUser:$basic -AcceptEula
}
# Prompt for a path to save a CSV file and continue to prompt until we get a path we can use
while ($true) {
$destination = Read-Host -Prompt "Path to save CSV file"
$file = New-Item -Path $destination -ItemType File -Force
if ($null -ne $file) {
break
}
}
class GpsCoordinate {
<#
GPS coordinates in Milestone are available in the GisPoint property on a Camera object
however the format is "POINT (X Y)" or sometimes "POINT (X Y Z)" where Z is unused.
GPS coordinates are often expressed as "latitude, longitude" but on a typical coordinate
plane the X represents the longitude value and Y represents latitude.
This class has a "FromGisPoint" method which takes the GisPoint value from Milestone and
parses it into a new GpsCoordinate object with a Latitude and Longitude property you can
use, or by calling .ToString() you can get the "Latitude, Longitude" format.
#>
[double]$Latitude
[double]$Longitude
static [GpsCoordinate]FromGisPoint([string]$GisPoint) {
$coordinates = [GpsCoordinate]::new()
if ($GisPoint -eq 'POINT EMPTY') {
return $coordinates
}
$temp = $GisPoint.Substring(7, $GisPoint.Length - 8)
$long, $lat, $null = $temp -split ' '
$coordinates.Latitude = [double]$lat
$coordinates.Longitude = [double]$long
return $coordinates
}
[string]ToString() {
return ($this.Latitude.ToString() + ", " + $this.Longitude.ToString())
}
}
$results = New-Object System.Collections.Generic.List[pscustomobject]
try {
# Enumerate over all the cameras in the system, parse their "GisPoint" values into latitude and longitude, show it in the console and export it to CSV.
foreach ($hardware in Get-Hardware) {
foreach ($camera in $hardware | Get-Camera) {
$coordinates = [GpsCoordinate]::FromGisPoint($camera.GisPoint)
$result = [pscustomobject]@{
Name = $camera.Name
Address = ([uri]$hardware.Address).Host
Location = $coordinates.ToString()
Latitude = $coordinates.Latitude
Longitude = $coordinates.Longitude
}
$results.Add($result)
$result
}
}
$results | Export-Csv -Path $destination -NoTypeInformation
}
finally {
Disconnect-ManagementServer
}
# Make sure we have permission to execute ps1 files within the scope of this running process only
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force -Confirm:$false
if ($null -eq (Get-Module -ListAvailable -Name MilestonePSTools)) {
# MilestonePSTools is not installed so let's take care of some prerequisits for using Install-Module to install it
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
$nugetProvider = Get-PackageProvider -ListAvailable -Name NuGet -ErrorAction Ignore
if ($null -eq $nugetProvider -or $nugetProvider.Version -lt [version]'2.8.5.201') {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
}
$psgetModule = Get-Module -ListAvailable -Name PowerShellGet -ErrorAction Ignore
if ($null -eq $psgetModule -or $psgetModule.Version -lt [version]'2.2.5') {
Install-Module PowerShellGet -MinimumVersion 2.2.5 -Force -Confirm:$false
}
# Now we install MilestonePSTools and by extension, MipSdkRedist
Install-Module MilestonePSTools -Force -Confirm:$false
}
# Prompt for Milestone VMS login information and continue to prompt until we are successfully connected
while ($null -eq (Get-ManagementServer -ErrorAction Ignore)) {
$server = Read-Host -Prompt "Milestone VMS server address"
$credential = Get-Credential -Message "Milestone VMS user"
$basic = "y" -eq (Read-Host -Prompt "Is this a basic user (y/n)?")
Connect-ManagementServer -Server $server -Credential $credential -BasicUser:$basic -AcceptEula
}
# Prompt for a path to save a CSV file and continue to prompt until we get a path we can use
while ($true) {
$destination = Read-Host -Prompt "Path to save CSV file"
$file = New-Item -Path $destination -ItemType File -Force
if ($null -ne $file) {
break
}
}
class GpsCoordinate {
<#
GPS coordinates in Milestone are available in the GisPoint property on a Camera object
however the format is "POINT (X Y)" or sometimes "POINT (X Y Z)" where Z is unused.
GPS coordinates are often expressed as "latitude, longitude" but on a typical coordinate
plane the X represents the longitude value and Y represents latitude.
This class has a "FromGisPoint" method which takes the GisPoint value from Milestone and
parses it into a new GpsCoordinate object with a Latitude and Longitude property you can
use, or by calling .ToString() you can get the "Latitude, Longitude" format.
#>
[double]$Latitude
[double]$Longitude
static [GpsCoordinate]FromGisPoint([string]$GisPoint) {
$coordinates = [GpsCoordinate]::new()
if ($GisPoint -eq 'POINT EMPTY') {
return $coordinates
}
$temp = $GisPoint.Substring(7, $GisPoint.Length - 8)
$long, $lat, $null = $temp -split ' '
$coordinates.Latitude = [double]$lat
$coordinates.Longitude = [double]$long
return $coordinates
}
[string]ToString() {
return ($this.Latitude.ToString() + ", " + $this.Longitude.ToString())
}
}
$results = New-Object System.Collections.Generic.List[pscustomobject]
try {
$cameras = Select-Camera -Title 'Select cameras for GPS Information Export' -AllowFolders -RemoveDuplicates
foreach ($camera in $cameras) {
$hardware = Get-Hardware -HardwareId ($camera.ParentItemPath.Substring(9, 36))
$coordinates = [GpsCoordinate]::FromGisPoint($camera.GisPoint)
$result = [pscustomobject]@{
Name = $camera.Name
Address = ([uri]$hardware.Address).Host
Location = $coordinates.ToString()
Latitude = $coordinates.Latitude
Longitude = $coordinates.Longitude
}
$results.Add($result)
$result
}
$results | Export-Csv -Path $destination -NoTypeInformation
}
finally {
Disconnect-ManagementServer
}
@joshooaj
Copy link
Copy Markdown
Author

Here's an example of the information shown in the terminal when running. The same information is also exported to a CSV file at the user-specified path.

2021-06-16 13_50_09-Windows Sandbox

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment