PSMetrolink.psm1
function Get-Metrolink { <# .SYNOPSIS Retrieves live data from the Geater Manchester Metrolink system using the TFGM/Metrolink API. .DESCRIPTION Uses 'Invoke-RestMethod' and the TFGM/Metrolink API to return live data from the Greater Manchester Metrolink system. .PARAMETER Key The API subscription key used to make the query. .PARAMETER Station If used, the query will only retrieve data for the specified station. .PARAMETER Uri Specifies the URI to make the API call to. This is provided as a failsafe in case the included value becomes incorrect. .EXAMPLE $Key = 1234567890asdfghjkl Get-Metrolink -Key $SubscriptionKey -Station "Radcliffe" Destination : Bury Wait : 6 Carriages : Double Status : Due Line : Bury Station : Radcliffe Destination : Bury Wait : 19 Carriages : Double Status : Due Line : Bury Station : Radcliffe Destination : Piccadilly Wait : 9 Carriages : Double Status : Due Line : Bury Station : Radcliffe Destination : Piccadilly Wait : 21 Carriages : Double Status : Due Line : Bury Station : Radcliffe .INPUTS String(s) .OUTPUTS PSCustomObject .NOTES This cmdlet requires a subscription key to the Open Data Service Version 2.0 API provided by TFGM. .LINK https://docs.microsoft.com/powershell/module/microsoft.powershell.utility/invoke-restmethod https://developer.tfgm.com/ https://developer.tfgm.com/docs/services #> [CmdletBinding(ConfirmImpact = 'Low', SupportsShouldProcess = $True)] [Alias("Get-Tram", "Get-Met")] [OutputType([PSCustomObject])] param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, HelpMessage = "The API key used for the query")] [string] $Key, [Parameter(Mandatory = $False, Position = 1, HelpMessage = "A specific Metrolink station")] [ValidateSet( "Abraham Moss", "Altrincham", "Anchorage", "Ashton Moss", "Ashton West", "Ashton-Under-Lyne", "Audenshaw", "Baguley", "Barlow Moor Road", "Benchill", "Besses O’ Th’ Barn", "Bowker Vale", "Broadway", "Brooklands", "Burton Road", "Bury", "Cemetery Road", "Central Park", "Chorlton", "Clayton Hall", "Cornbrook", "Crossacres", "Crumpsall", "Dane Road", "Deansgate - Castlefield", "Derker", "Didsbury Village", "Droylsden", "East Didsbury", "Eccles", "Edge Lane", "Etihad Campus", "Exchange Quay", "Exchange Square", "Failsworth", "Firswood", "Freehold", "Harbour City", "Heaton Park", "Hollinwood", "Holt Town", "Kingsway Business Park", "Ladywell", "Langworthy", "Manchester Airport", "Market Street", "Martinscroft", "MediaCityUK", "Milnrow", "Monsall", "Moor Road", "Navigation Road", "New Islington", "Newbold", "Newhey", "Newton Heath and Moston", "Northern Moor", "Old Trafford", "Oldham Central", "Oldham King Street", "Oldham Mumps", "Peel Hall", "Piccadilly", "Piccadilly Gardens", "Pomona", "Prestwich", "Queens Road", "Radcliffe", "Robinswood Road", "Rochdale Railway Station", "Rochdale Town Centre", "Roundthorn", "Sale", "Sale Water Park", "Salford Quays", "Shadowmoss", "Shaw and Crompton", "Shudehill", "South Chadderton", "St Peter's Square", "St Werburgh's Road", "Stretford", "Timperley", "Trafford Bar", "Velopark", "Victoria", "Weaste", "West Didsbury", "Westwood", "Whitefield", "Withington", "Wythenshawe Park", "Wythenshawe Town Centre" )] #[ValidateSet("test_me")] [string] $Station, [Parameter(Mandatory = $False, Position = 2, HelpMessage = "The API uri")] [string] $Uri = "https://api.tfgm.com/odata/Metrolinks" ) if ($PSBoundParameters.ContainsKey("Debug")) { $DebugPreference = "Continue" } if ($PSCmdlet.ShouldProcess($Uri, "Query API")) { try { Write-Verbose -Message "Defining query parameters." $QueryParams = @{ Uri = $Uri Method = "Get" Headers = @{ "Ocp-Apim-Subscription-Key" = $Key } ErrorAction = "Stop" } Write-Verbose -Message "Querying API." $QueryResults = (Invoke-RestMethod @QueryParams).Value } catch { $PSCmdlet.ThrowTerminatingError($_) } } if ($PSCmdlet.ShouldProcess($Uri, "Process query results")) { try { $ProcessedResults = forEach ($WorkingResult in $QueryResults) { # Here begins the work to re-format the default object returned by the API. # By default you get as many as three trams/'events' per-object. # This should be 1:1 in my opinion. $i = 0 do { $DestToken = "Dest$i" $StatusToken = "Status$i" $CarriagesToken = "Carriages$i" $WaitToken = "Wait$i" # Some logic here to compare WorkingResult.StationLocation to the $Station value would be useful for the optional parameter. if ((-not ($Station)) -or (($Null -ne $Station) -and ($WorkingResult.StationLocation -match $Station))) { Write-Debug -Message "Passed conditional station validation: '$($WorkingResult.StationLocation)'." $Tram = [PSCustomObject]@{ # I've been calling this a tram-stop(ping) event, because I don't know the technical name of it. Destination = ( $WorkingResult.PSObject.Properties | Where-Object { ( $_.Name -match $DestToken ) -and ( $_.Value ) } ).Value Wait = ([int] ( $WorkingResult.PSObject.Properties | Where-Object { ( $_.Name -match $WaitToken ) -and ( $_.Value ) } ).Value) Carriages = ( $WorkingResult.PSObject.Properties | Where-Object { ( $_.Name -match $CarriagesToken ) -and ( $_.Value ) } ).Value Status = ( $WorkingResult.PSObject.Properties | Where-Object { ( $_.Name -match $StatusToken ) -and ( $_.Value ) } ).Value Line = ( $WorkingResult.Line) Station = ( $WorkingResult.StationLocation) } if (($Tram.Wait) -and ($Tram.Status)) { # This is a valid tram-stopping event, so we can output it. Write-Debug -Message "Passed basic object property validation." $Tram } else { # This isn't. Write-Debug -Message "Failed basic object property validation." } } else { Write-Debug -Message "Failed station validation: '$($WorkingResult.StationLocation)'." } $i++ } while ( ($WorkingResult.PSObject.Properties | Where-Object { ($_.Name -match $DestToken) -and ($_.Value) }) ) } } catch { $PSCmdlet.ThrowTerminatingError($_) } if ($ProcessedResults) { Write-Verbose -Message "Outputting results." $ProcessedResults | Sort-Object "Line", "Station", "Destination", "Wait" } else { Write-Verbose -Message "No results found." } } } |