Viewing entries tagged
api

PowerShell: Fun with Weather Underground's API (part 2)

PowerShell: Fun with Weather Underground's API (part 2)

In the last post we learned how to use Weather Underground's API to resolve a city name and get data back from it. Once we get those two URLs we can use them to get data back from the API.  I also tied this into my LIFX light, which I posted about here.

Requirements

Setup

[cmdletbinding()]
param(
    [string]
    $city = (Read-Host "City?"),
    [string]
    $forecast = 'forecast',
    [boolean]
    $sendEmail,
    [boolean]
    $lifx,
    [boolean]
    $sendAlertEmail
)

if (!$foregroundColor) {$foregroundColor = 'green'}
$baseURL      = 'http://api.wunderground.com/api/'
$apiKey       = 'yourAPIKey'
$acceptHeader = 'application/json'

#"password" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File .\emlpassword.txt

$emailPass    = Get-Content .\emlpassword.txt | ConvertTo-SecureString  
$weatherList  = Get-Content .\emails.txt
$alertList    = Get-Content .\alertEmails.txt
$emailUser    = 'yourEmailUsername'
$emailFrom    = 'youremail@service.com'
$smtpServer   = 'smtp.gmail.com'
$smtpPort     = '587'

The Setup

  • Name: Get-Weather.ps1
  • Variables:
    • $baseURL = (Weather Underground's base URL for the API, should be fine with default).
    • $apiKey = Your API key that you get from signing up.
    • $acceptHeader = Header/formatting settings (default is good).
    • $emailPass = Set your password by running the commented line above it. This will be user/machine encrypted.
    • $weatherList = Create a text file (named emails.txt) in the script directory that contains a list of people to email the forecasts to. 
    • $alertList  = Create a text file (named alertEmails.txt) in the script directory that contains a list of people to email/text alerts to. I made this different so I could setup text message alerts.
    • $emailUser = Your user name for the email address we're sending from.
    • $emailFrom  = Your from email address.
    • $smtpServer  = Your SMTP server. Default is Google's.
    • $smtpPort = Your SMTP server's port. This is Google's default.
  • Parameters
    • city (will prompt for one if left blank)
    • forecast (Will default to 4 day which is the value 'forecast')
      Values:
      • forecast  (4 day)
      • hourly (next 36 hours)
      • camera (emails an email address a random webcam from the city specified)
    • sendEmail (accepts $true, defaults to $false) This is for sending the email forecast.
    • lifx (accepts $true, defaults to $false) This is for LIFX light integration. Currently it will flash your LIFX light red when there is an alert. More coming soon with this!
    • sendAlertEmail (accepts $true, defaults to $false) This is to send an email (which I use the carrier's email to text address to text myself) if an alert is found.

The first function: Get-Weather

This function will first use the auto-complete API and then from there create the URLs and use them to get the weather data. It will also return the API results at the end. That way you can run the script like this:

$weatherChicago = .\Get-Weather.ps1 -city Chicago

And it will return what the API returns, as well as display some information:

The variable $weatherChicago will contain what the API returned. 

With this information you can really drill down and see what is available. It was by doing this that I got the initial ideas for parts of this script. Here's an example of the information returned via:

$weatherChicago.current_observation

After the function finds the city and displays the basic info, it then moves forward to check which forecast was specified and if that forecast is to be emailed. 

Get-Weather function code

function Get-Weather {
    param()
   
    $findMe = $city
    $find   = Invoke-RestMethod -Uri "http://autocomplete.wunderground.com/aq?query=$findMe"

    if ($find) {
        
        $cityAPI  = $find.Results[0].l
        $city     = $find.Results[0].name
        
        $fullURL  = $baseURL + $apiKey + "/features/conditions/hourly/forecast/webcams/alerts" + "$cityAPI.json"
        $radarURL = "http://api.wunderground.com/api/$apiKey/animatedradar/animatedsatellite" + "$cityAPI.gif?num=6&delay=50&interval=30"
        
        Write-Host `n"API URLS for $city" -foregroundcolor $foregroundColor
        Write-Host `t$fullURL
        Write-Host `t$radarURL
        
        $weatherForecast = Invoke-RestMethod -Uri $fullURL -ContentType $acceptHeader
        
        $currentCond     = $weatherForecast.current_observation
        
        Write-Host `n"Current Conditions for: $city" -foregroundColor $foregroundColor
        Write-Host $currentCond.Weather 
        Write-Host "Temperature:" $currentCond.temp_f"F"
        Write-Host "Winds:" $currentCond.wind_string
        
        $curAlerts = $weatherForecast.alerts 
        
        if ($curAlerts) {
            
            if ($lifx) { Get-LIFXAPI -action flashcolor -brightness 1 -color Red -state on }
            
            $typeName = Get-WeatherFunction -Weather 'alert' -value $weatherForecast.alerts
            
            $alertDate  = $curAlerts.date
            $alertExp   = $curAlerts.expires 
            $alertMsg   = $curAlerts.message
            
            Write-Host `n"Weather Alert! ($typeName)" -foregroundcolor Red
            Write-Host "Date: $alertDate Expires: $alertExp"
            Write-Host "$alertMsg"    
            
            if ($sendAlertEmail) {

                Foreach ($email in $alertList) {
                    
                    Send-WeatherEmail -to $email -Subject "Weather Alert!" -Body "Alert Type: $typeName City: $city Message: $alertMsg"
                
                }
            }                  

        } 
        
    }

    Switch ($forecast) {
    
        {$_ -eq 'hourly'} {
 
            if ($sendEmail) {

                $hourlyForecast = $weatherForecast.hourly_forecast
                
                $body = "<p></p>"
                $body += "<p>Here is your hourly forecast!</p>"
                
                $selCam   = Get-Random $weatherForecast.webcams.count
                
                $camImg   = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
                $camName  = $weatherForecast.webcams[$selCam].linktext
                $camLink  = $weatherForecast.webcams[$selCam].link
                
                $body += "<p>Random webcam shot from: <a href=`"$camLink`">$camName</a></p>"
                $body += "<p><img src=`"$camImg`"></p>"                 
                                
                $body += "<p>$city Radar:</p>"
                $body += "<p><img src=`"$radarURL`"></p>"  
                
                if ($curAlerts) {
                    
                    $body += "<p><b><font color=`"red`">Weather Alert! ($typeName)</font></b></p>"
                    $body += "<p>Date: $alertDate Expires: $alertExp</p>"
                    $body += "<p>$alertMsg</p>"    
    
                }           
                
                foreach ($hour in $hourlyForecast) {
                    
                    $body += "<p></p>"
                    $body += "<p></p>"
                    
                    $prettyTime       = $hour.fcttime.pretty
                    $hourTemp         = $hour.temp.english  
                    $hourImg          = $hour.icon_url
                    
                    [int]$hourChill   = $hour.windchill.english
                    
                    if ($hourChill -eq -9999) {
                    
                        $hourChilltxt = 'N/A'
                        
                    } else {
                        
                        $hourChilltxt = $hourChill.ToString() + 'F'
                   
                    }
                                        
                    $hourWind         = $hour.wspd.english
                    $windDir          = $hour.wdir.dir
                    $hourUV           = $hour.uvi
                    $dewPoint         = $hour.dewpoint.english
                    $hourFeels        = $hour.feelslike.english
                    $hourHum          = $hour.humidity
                    $conditions       = $hour.condition
                    [int]$hourPrecip  = $hour.pop
                    
                    $popText = Get-WeatherFunction -Weather 'preciptext' -value $hourPrecip
                    
                    $body += "<p><b>$prettyTime</b></p>"
                    $body += "<p><img src=`"$hourImg`">$conditions</p>"
                    $body += "<p>Chance of precipitation: $hourPrecip% / $popText</p>"
                    $body += "<p>Current Temp: $hourTemp`F Wind Chill: $hourChilltxt Feels Like: $hourFeels`F</p>"
                    $body += "<p>Dew Point: $dewPoint</p>"
                    $body += "<p>Wind Speed: $hourWind`mph Direction: $windDir</p>"
                    $body += "<p>Humidity: $hourHum%</p>"
                    $body += "<p>UV Index: $hourUV"     
                    
                }
                
                foreach ($email in $weatherList) {Send-WeatherEmail -To $email -Subject "Your hourly forecast for $city" -body $body}
            
            }            
        
        }
        
        {$_ -eq 'forecast'} {                
              
            if ($sendEmail) {

                $todayForecast = $weatherForecast.forecast.simpleforecast.forecastday
                
                $body = "<p></p>"
                $body += "<p>Here is your 4 day forecast!</p>"
                
                $selCam   = Get-Random $weatherForecast.webcams.count
                
                $camImg   = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
                $camName  = $weatherForecast.webcams[$selCam].linktext
                $camLink  = $weatherForecast.webcams[$selCam].link
                
                $body += "<p>Random webcam shot from: <a href=`"$camLink`">$camName</a></p>"
                $body += "<p><img src=`"$camImg`"></p>"                 
                
                $body += "<p>$city Radar:</p>"
                $body += "<p><img src=`"$radarURL`"></p>"      
                
                $curAlerts = $weatherForecast.alerts 
                
                if ($curAlerts) {
                    
                    $body += "<p><b><font color=`"red`">Weather Alert! ($typeName)</font></b></p>"
                    $body += "<p>Date: $alertDate Expires: $alertExp</p>"
                    $body += "<p>$alertMsg</p>"    

                }                   
               
                foreach ($day in $todayForecast) {
                    
                    $body += "<p></p>"
                    $body += "<p></p>"
                    
                    $dayImg          = $day.icon_url
                    $dayMonth        = $day.date.monthname
                    $dayDay          = $day.date.day
                    $dayName         = $day.date.weekday
                    $dayHigh         = $day.high.fahrenheit  
                    $dayLow          = $day.low.fahrenheit
                    $maxWind         = $day.maxwind.mph
                    $aveWind         = $day.avewind.mph
                    $aveHum          = $day.avehumidity
                    $conditions      = $day.conditions
                    [int]$dayPrecip  = $day.pop
                    
                    $popText = Get-WeatherFunction -Weather 'preciptext' -value $dayPrecip
                    
                    $body += "<p><b>$dayName, $dayMonth $dayDay</b></p>"
                    $body += "<p><img src=`"$dayImg`">$conditions</p>"
                    $body += "<p>Chance of precipitation: $dayPrecip% / $popText</p>"
                    $body += "<p>High: $dayHigh`F Low: $dayLow`F</p>"
                    $body += "<p>Ave Winds: $aveWind`mph Max Winds: $maxWind`mph</p>"
                    $body += "<p>Humidity: $aveHum%</p>"
         
                }

                foreach ($email in $weatherList) {Send-WeatherEmail -To $email -Subject "Your 4 day forecast for $city" -body $body}
            
            }  
            
        }

        {$_ -eq 'camera'} {
            
            $selCam    = Get-Random $weatherForecast.webcams.count
            
            $camImg    = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
            $camName   = $weatherForecast.webcams[$selCam].linktext
            $camLink   = $weatherForecast.webcams[$selCam].link
            
            $fileExt   = $camImg.SubString($camImg.LastIndexOf("."),4)
            
            $cityShort = $city.substring(0,$city.lastindexof(","))
            
            $fileName  = $cityShort + $fileExt
            
            $location  = (Get-Location).Path
            
            $camFile   = Invoke-WebRequest -Uri $camImg -OutFile "$location\$fileName"   
            
            $file = $location + "\" + $fileName
            
            $gallery = 'YourSquareSpaceGalleryOrEmailToSendAttachmentTo' 
            
            $SMTPClient             = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
            $SMTPMessage            = New-Object System.Net.Mail.MailMessage($emailFrom,$gallery,"$city cam","$city cam")
            $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($emailUser,$emailPass)
            
            $att                    = New-Object Net.Mail.Attachment($file)
            $SMTPClient.EnableSsl   = $true
           
            Switch (($fileName.substring($fileName.LastIndexOf(".")+1)).tolower()) {
                
                {$_ -like "*png*"} {
                
                    $typeExt = 'png'    
                    
                }
                
                {$_ -like "*jpg*"} {
                
                    $typeExt = 'jpg'     
                    
                }
                
                {$_ -like "*gif*"} {
                    
                    $typeExt = 'gif' 
                    
                }                                
                
            }
            
            $SMTPMessage.Attachments.Add($att)
            ($smtpmessage.Attachments).contenttype.mediatype = "image/$typeExt"
            
            $SMTPClient.Send($SMTPMessage)
            
            $att.Dispose()
            $SMTPMessage.Dispose()
            
            Remove-Item $file
            
        }
    
    } 
    
    Return $weatherForecast

}

Let's take a look at some of the code

The 'camera' option uses its own email sending commands since I had to change the MIME type of the attachment. There is also a variable used to specify where to send the email to. This variable is within the switch for now (until I clean it up!) as $gallery. You'll want to change that to an email address you want to receive the attached webcam shot.

 For some reason when sending an image file PowerShell sends it with type information stating it is an application. The following code is what I used to fix that. I noticed this issue when it wouldn't post to SquareSpace unless I first sent it to my Gmail, and then forwarded it to SquareSpace. Once I forwarded it I noticed it would post. It was then I decided to take a look at the full email details and saw the difference in attachment types.

That led me to write the following section of code so I could send the random webcam shot to the gallery and have it post.

{$_ -eq 'camera'} {
            
            $selCam    = Get-Random $weatherForecast.webcams.count
            
            $camImg    = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
            $camName   = $weatherForecast.webcams[$selCam].linktext
            $camLink   = $weatherForecast.webcams[$selCam].link
            
            $fileExt   = $camImg.SubString($camImg.LastIndexOf("."),4)
            
            $cityShort = $city.substring(0,$city.lastindexof(","))
            
            $fileName  = $cityShort + $fileExt
            
            $location  = (Get-Location).Path
            
            $camFile   = Invoke-WebRequest -Uri $camImg -OutFile "$location\$fileName"   
            
            $file = $location + "\" + $fileName
            
            $gallery = 'your SquareSpace gallery URL or Email address to send pictures to' 
            
            $SMTPClient             = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
            $SMTPMessage            = New-Object System.Net.Mail.MailMessage($emailFrom,$gallery,"$city cam","$city cam")
            $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($emailUser,$emailPass)
            
            $att                    = New-Object Net.Mail.Attachment($file)
            $SMTPClient.EnableSsl   = $true
           
            Switch (($fileName.substring($fileName.LastIndexOf(".")+1)).tolower()) {
                
                {$_ -like "*png*"} {
                
                    $typeExt = 'png'    
                    
                }
                
                {$_ -like "*jpg*"} {
                
                    $typeExt = 'jpg'     
                    
                }
                
                {$_ -like "*gif*"} {
                    
                    $typeExt = 'gif' 
                    
                }                                
                
            }
            
            $SMTPMessage.Attachments.Add($att)
            ($smtpmessage.Attachments).contenttype.mediatype = "image/$typeExt"
            
            $SMTPClient.Send($SMTPMessage)
            
            $att.Dispose()
            $SMTPMessage.Dispose()
            
            Remove-Item $file
            
        }

The above code downloads the file, looks at what type of image it is, and then changes the type accordingly. After that it constructs an email object, attaches the file, send the email, and finally removes the file.

The next function is Send-WeatherEmail

function Send-WeatherEmail {
    [cmdletbinding()]
    param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]
    $To,
    
    [string]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    $Subject,
    
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    $Body,
    
    [string]
    $attachment
    )

    if (!$to)      {Write-Error "No recipient specified";break}
    if (!$subject) {Write-Error "No subject specified";break}
    if (!$body)    {Write-Error "No body specified";break}
   
    $gmailCredential = New-Object System.Management.Automation.PSCredential($emailUser,$emailPass)
       
    Send-MailMessage -To $to -From $emailFrom -Body $body -BodyAsHtml:$true -Subject $Subject -SmtpServer $smtpServer -Port $smtpPort -UseSsl -Credential $gmailCredential
 
}

This function is a short and sweet function that wraps up Send-MailMessage so you can use it throughout the script easily.

Now onto the function Get-WeatherFunction

function Get-WeatherFunction {
    [cmdletbinding()]
    param(
        [string]
        $weather,
        $value       
    )
    
    Switch ($weather) {
        
        {$_ -eq 'preciptext'} {
        
            Switch ($value) {
                
                {$_ -lt 20} {
                    
                    $popText = 'No mention'
                    
                }
                
                {$_ -eq 20} {
                    
                    $popText = 'Slight Chance'
                    
                }
                
                {($_ -lt 50 -and $_ -gt 20)} {
                    
                    $popText = 'Chance'
                    
                }
                
                {$_ -eq 50} {
                    
                    $popText = 'Good chance'
                    
                }
                
                {($_ -lt 70 -and $_ -gt 50)} {
                    
                    $popText = 'Likely'
                    
                }
                
                {$_ -ge 70} {
                    
                    $popText = 'Extremely likely'
                    
                }
                
            }
            
            Return $popText
            
        }   
        
        {$_ -eq 'alert'}    {
            
            Switch ($curAlerts.type) {
                
                'HEA' {$typeName = 'Heat Advisory'}
                'TOR' {$typeName = 'Tornado Warning'}
                'TOW' {$typeName = 'Tornado Watch'}
                'WRN' {$typeName = 'Severe Thunderstorm Warning'}
                'SEW' {$typeName = 'Severe Thunderstorm Watch'}
                'WIN' {$typeName = 'Winter Weather Advisory'}
                'FLO' {$typeName = 'Flood Warning'}
                'WAT' {$typeName = 'Flood Watch / Statement'}
                'WND' {$typeName = 'High Wind Advisory'}
                'SVR' {$typeName = 'Severe Weather Statement'}
                'HEA' {$typeName = 'Heat Advisory'}
                'FOG' {$typeName = 'Dense Fog Advisory'}
                'SPE' {$typeName = 'Special Weather Statement'}
                'FIR' {$typeName = 'Fire Weather Advisory'}
                'VOL' {$typeName = 'Volcanic Activity Statement'}
                'HWW' {$typeName = 'High Wind Warning'}
                'REC' {$typeName = 'Record Set'}
                'REP' {$typeName = 'Public Reports'}
                'PUB' {$typeName = 'Public Information Statement'}
                    
            }
                
            Return $typeName
    
        }    
    }
    
}

This is perhaps one of the gnarliest functions I've ever named. I'll have to rethink the name, perhaps. For now, let's look at what it does. 

Currently it will take the parameter $weather and take different actions based on the input. If you specify 'preciptext' it will return the precipitation chance in text format based on the number it is given. For example if you run: 

Get-WeatherFunction -Weather 'preciptext' -value 71

It will return 'Extremely Likely'.

If you specify 'alert' then you'll be able to provide the 3 letter alert code Weather Underground returns via the API and return the full alert text. For example: 

Get-WeatherFunction -Weather 'alert' -value 'HEA'

This would return 'Heat Advisory'.

The final function: Get-LIFXApi

function Get-LIFXApi {
[cmdletbinding()]
param(
    [string]
    $action = 'setstate',
    [string]
    $state = 'on',
    [string]
    $color = 'white',
    [double]
    $brightness = '0.4'
)

$apiKey          = 'YourLifxApiKey'
$base64Key       =  [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($apiKey)))
$headers         =  @{Authorization=("Basic {0}" -f $base64Key)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptheader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights/'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

$ninjaLights     = Invoke-RestMethod -headers $headers -Uri $allURL

function Change-LightState {
    [cmdletbinding()]
    param(
        [string]
        $state,
        [string]
        $color,
        [double]
        $brightness,
        [string]
        $selector
    )
    
    $ninjaID  = $ninjaLights.id
    $selector = 'id:' + $ninjaID
    $fullURL  = $baseurl + $selector + '/state'

    $payloadBuilder = "{
                    `"power`": `"$state`",
                    `"color`": `"$color`",
                    `"brightness`" : $brightness 
                    }"

    Write-Host "Changing light to:" -ForegroundColor $foregroundcolor
    Write-Host `t"State     :" $state
    Write-Host `t"Color     :" $color
    Write-Host `t"Brightness:" ($brightness * 100)"%" `n

    $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadBuilder
    
    Write-Host "API status:" -ForegroundColor $foregroundcolor
    Write-Host `t"Light :" $stateReturn.results.label
    Write-Host `t"Status:" $stateReturn.results.status `n
    
    
}

Switch ($action) {
    
    'setstate' { Change-LightState -state $state -color $color -brightness $brightness -selector $selector }
    
    'fluxtest' { 
        
        $originalBrightness = $ninjaLights.Brightness
        $originalColor      = $ninjalights.Color
        $originalState      = $ninjalights.Power
        $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
          
        $i = 0
        
        While ($i -le 20) {
            
            $color              = Get-Random $colors
            [double]$brightness = "{0:n2}" -f (Get-Random 0.99)
 
            Change-LightState -color $color -brightness $brightness -selector $selector -state $state
            Start-Sleep -seconds 1
            $i++
            
        }
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector  
        
    } 
    
    'flashcolor' {
        
        $originalBrightness = $ninjaLights.Brightness
        $originalColor      = $ninjalights.Color
        $originalState      = $ninjalights.Power
        $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
        
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
        Start-Sleep -Seconds 1
                
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
        Start-Sleep -Seconds 1        
        
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
                        
    }
}    
    
    
}

I wrote the above function as a script initially when I learned that LIFX provides and API you can use to control your light! It is currently called if the parameter lifx is $true, and if there is a current alert.

if ($lifx) { Get-LIFXAPI -action flashcolor -brightness 1 -color Red -state on }

It then performs the switch option 'flashcolor' which flashes the light red at 100%. It then returns the light to whatever setting it was set to before it started flashing. To get this function to work you'll need to change $apiKey to your LIFX Cloud API key. For more details on working with the LIFX API, check out my post here.

Full code

[cmdletbinding()]
param(
    [string]
    $city = (Read-Host "City?"),
    [string]
    $forecast = 'forecast',
    [boolean]
    $sendEmail,
    [boolean]
    $lifx,
    [boolean]
    $sendAlertEmail
)

if (!$foregroundColor) {$foregroundColor = 'green'}
$baseURL      = 'http://api.wunderground.com/api/'
$apiKey       = 'yourAPIKey'
$acceptHeader = 'application/json'

#"password" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File .\emlpassword.txt

$emailPass    = Get-Content .\emlpassword.txt | ConvertTo-SecureString  
$weatherList  = Get-Content .\emails.txt
$alertList    = Get-Content .\alertEmails.txt
$emailUser    = 'yourEmailUsername'
$emailFrom    = 'youremail@service.com'
$smtpServer   = 'smtp.gmail.com'
$smtpPort     = '587'

function Get-Weather {
    param()
   
    $findMe = $city
    $find   = Invoke-RestMethod -Uri "http://autocomplete.wunderground.com/aq?query=$findMe"

    if ($find) {
        
        $cityAPI  = $find.Results[0].l
        $city     = $find.Results[0].name
        
        $fullURL  = $baseURL + $apiKey + "/features/conditions/hourly/forecast/webcams/alerts" + "$cityAPI.json"
        $radarURL = "http://api.wunderground.com/api/$apiKey/animatedradar/animatedsatellite" + "$cityAPI.gif?num=6&delay=50&interval=30"
        
        Write-Host `n"API URLS for $city" -foregroundcolor $foregroundColor
        Write-Host `t$fullURL
        Write-Host `t$radarURL
        
        $weatherForecast = Invoke-RestMethod -Uri $fullURL -ContentType $acceptHeader
        
        $currentCond     = $weatherForecast.current_observation
        
        Write-Host `n"Current Conditions for: $city" -foregroundColor $foregroundColor
        Write-Host $currentCond.Weather 
        Write-Host "Temperature:" $currentCond.temp_f"F"
        Write-Host "Winds:" $currentCond.wind_string
        
        $curAlerts = $weatherForecast.alerts 
        
        if ($curAlerts) {
            
            if ($lifx) { Get-LIFXAPI -action flashcolor -brightness 1 -color Red -state on }
            
            $typeName = Get-WeatherFunction -Weather 'alert' -value $weatherForecast.alerts
            
            $alertDate  = $curAlerts.date
            $alertExp   = $curAlerts.expires 
            $alertMsg   = $curAlerts.message
            
            Write-Host `n"Weather Alert! ($typeName)" -foregroundcolor Red
            Write-Host "Date: $alertDate Expires: $alertExp"
            Write-Host "$alertMsg"    
            
            if ($sendAlertEmail) {

                Foreach ($email in $alertList) {
                    
                    Send-WeatherEmail -to $email -Subject "Weather Alert!" -Body "Alert Type: $typeName City: $city Message: $alertMsg"
                
                }
            }                  

        } 
        
    }

    Switch ($forecast) {
    
        {$_ -eq 'hourly'} {
 
            if ($sendEmail) {

                $hourlyForecast = $weatherForecast.hourly_forecast
                
                $body = "<p></p>"
                $body += "<p>Here is your hourly forecast!</p>"
                
                $selCam   = Get-Random $weatherForecast.webcams.count
                
                $camImg   = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
                $camName  = $weatherForecast.webcams[$selCam].linktext
                $camLink  = $weatherForecast.webcams[$selCam].link
                
                $body += "<p>Random webcam shot from: <a href=`"$camLink`">$camName</a></p>"
                $body += "<p><img src=`"$camImg`"></p>"                 
                                
                $body += "<p>$city Radar:</p>"
                $body += "<p><img src=`"$radarURL`"></p>"  
                
                if ($curAlerts) {
                    
                    $body += "<p><b><font color=`"red`">Weather Alert! ($typeName)</font></b></p>"
                    $body += "<p>Date: $alertDate Expires: $alertExp</p>"
                    $body += "<p>$alertMsg</p>"    
    
                }           
                
                foreach ($hour in $hourlyForecast) {
                    
                    $body += "<p></p>"
                    $body += "<p></p>"
                    
                    $prettyTime       = $hour.fcttime.pretty
                    $hourTemp         = $hour.temp.english  
                    $hourImg          = $hour.icon_url
                    
                    [int]$hourChill   = $hour.windchill.english
                    
                    if ($hourChill -eq -9999) {
                    
                        $hourChilltxt = 'N/A'
                        
                    } else {
                        
                        $hourChilltxt = $hourChill.ToString() + 'F'
                   
                    }
                                        
                    $hourWind         = $hour.wspd.english
                    $windDir          = $hour.wdir.dir
                    $hourUV           = $hour.uvi
                    $dewPoint         = $hour.dewpoint.english
                    $hourFeels        = $hour.feelslike.english
                    $hourHum          = $hour.humidity
                    $conditions       = $hour.condition
                    [int]$hourPrecip  = $hour.pop
                    
                    $popText = Get-WeatherFunction -Weather 'preciptext' -value $hourPrecip
                    
                    $body += "<p><b>$prettyTime</b></p>"
                    $body += "<p><img src=`"$hourImg`">$conditions</p>"
                    $body += "<p>Chance of precipitation: $hourPrecip% / $popText</p>"
                    $body += "<p>Current Temp: $hourTemp`F Wind Chill: $hourChilltxt Feels Like: $hourFeels`F</p>"
                    $body += "<p>Dew Point: $dewPoint</p>"
                    $body += "<p>Wind Speed: $hourWind`mph Direction: $windDir</p>"
                    $body += "<p>Humidity: $hourHum%</p>"
                    $body += "<p>UV Index: $hourUV"     
                    
                }
                
                foreach ($email in $weatherList) {Send-WeatherEmail -To $email -Subject "Your hourly forecast for $city" -body $body}
            
            }            
        
        }
        
        {$_ -eq 'forecast'} {                
              
            if ($sendEmail) {

                $todayForecast = $weatherForecast.forecast.simpleforecast.forecastday
                
                $body = "<p></p>"
                $body += "<p>Here is your 4 day forecast!</p>"
                
                $selCam   = Get-Random $weatherForecast.webcams.count
                
                $camImg   = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
                $camName  = $weatherForecast.webcams[$selCam].linktext
                $camLink  = $weatherForecast.webcams[$selCam].link
                
                $body += "<p>Random webcam shot from: <a href=`"$camLink`">$camName</a></p>"
                $body += "<p><img src=`"$camImg`"></p>"                 
                
                $body += "<p>$city Radar:</p>"
                $body += "<p><img src=`"$radarURL`"></p>"      
                
                $curAlerts = $weatherForecast.alerts 
                
                if ($curAlerts) {
                    
                    $body += "<p><b><font color=`"red`">Weather Alert! ($typeName)</font></b></p>"
                    $body += "<p>Date: $alertDate Expires: $alertExp</p>"
                    $body += "<p>$alertMsg</p>"    

                }                   
               
                foreach ($day in $todayForecast) {
                    
                    $body += "<p></p>"
                    $body += "<p></p>"
                    
                    $dayImg          = $day.icon_url
                    $dayMonth        = $day.date.monthname
                    $dayDay          = $day.date.day
                    $dayName         = $day.date.weekday
                    $dayHigh         = $day.high.fahrenheit  
                    $dayLow          = $day.low.fahrenheit
                    $maxWind         = $day.maxwind.mph
                    $aveWind         = $day.avewind.mph
                    $aveHum          = $day.avehumidity
                    $conditions      = $day.conditions
                    [int]$dayPrecip  = $day.pop
                    
                    $popText = Get-WeatherFunction -Weather 'preciptext' -value $dayPrecip
                    
                    $body += "<p><b>$dayName, $dayMonth $dayDay</b></p>"
                    $body += "<p><img src=`"$dayImg`">$conditions</p>"
                    $body += "<p>Chance of precipitation: $dayPrecip% / $popText</p>"
                    $body += "<p>High: $dayHigh`F Low: $dayLow`F</p>"
                    $body += "<p>Ave Winds: $aveWind`mph Max Winds: $maxWind`mph</p>"
                    $body += "<p>Humidity: $aveHum%</p>"
         
                }

                foreach ($email in $weatherList) {Send-WeatherEmail -To $email -Subject "Your 4 day forecast for $city" -body $body}
            
            }  
            
        }

        {$_ -eq 'camera'} {
            
            $selCam    = Get-Random $weatherForecast.webcams.count
            
            $camImg    = $weatherforecast.webcams[$selCam].CURRENTIMAGEURL
            $camName   = $weatherForecast.webcams[$selCam].linktext
            $camLink   = $weatherForecast.webcams[$selCam].link
            
            $fileExt   = $camImg.SubString($camImg.LastIndexOf("."),4)
            
            $cityShort = $city.substring(0,$city.lastindexof(","))
            
            $fileName  = $cityShort + $fileExt
            
            $location  = (Get-Location).Path
            
            $camFile   = Invoke-WebRequest -Uri $camImg -OutFile "$location\$fileName"   
            
            $file = $location + "\" + $fileName
            
            $gallery = 'YourSquareSpaceGalleryOrEmailToSendAttachmentTo' 
            
            $SMTPClient             = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
            $SMTPMessage            = New-Object System.Net.Mail.MailMessage($emailFrom,$gallery,"$city cam","$city cam")
            $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($emailUser,$emailPass)
            
            $att                    = New-Object Net.Mail.Attachment($file)
            $SMTPClient.EnableSsl   = $true
           
            Switch (($fileName.substring($fileName.LastIndexOf(".")+1)).tolower()) {
                
                {$_ -like "*png*"} {
                
                    $typeExt = 'png'    
                    
                }
                
                {$_ -like "*jpg*"} {
                
                    $typeExt = 'jpg'     
                    
                }
                
                {$_ -like "*gif*"} {
                    
                    $typeExt = 'gif' 
                    
                }                                
                
            }
            
            $SMTPMessage.Attachments.Add($att)
            ($smtpmessage.Attachments).contenttype.mediatype = "image/$typeExt"
            
            $SMTPClient.Send($SMTPMessage)
            
            $att.Dispose()
            $SMTPMessage.Dispose()
            
            Remove-Item $file
            
        }
    
    } 
    
    Return $weatherForecast

}

function Send-WeatherEmail {
    [cmdletbinding()]
    param(
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    [string]
    $To,
    
    [string]
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    $Subject,
    
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    $Body,
    
    [string]
    $attachment
    )

    if (!$to)      {Write-Error "No recipient specified";break}
    if (!$subject) {Write-Error "No subject specified";break}
    if (!$body)    {Write-Error "No body specified";break}
   
    $gmailCredential = New-Object System.Management.Automation.PSCredential($emailUser,$emailPass)
       
    Send-MailMessage -To $to -From $emailFrom -Body $body -BodyAsHtml:$true -Subject $Subject -SmtpServer $smtpServer -Port $smtpPort -UseSsl -Credential $gmailCredential
 
}

function Get-WeatherFunction {
    [cmdletbinding()]
    param(
        [string]
        $weather,
        $value       
    )
    
    Switch ($weather) {
        
        {$_ -eq 'preciptext'} {
        
            Switch ($value) {
                
                {$_ -lt 20} {
                    
                    $popText = 'No mention'
                    
                }
                
                {$_ -eq 20} {
                    
                    $popText = 'Slight Chance'
                    
                }
                
                {($_ -lt 50 -and $_ -gt 20)} {
                    
                    $popText = 'Chance'
                    
                }
                
                {$_ -eq 50} {
                    
                    $popText = 'Good chance'
                    
                }
                
                {($_ -lt 70 -and $_ -gt 50)} {
                    
                    $popText = 'Likely'
                    
                }
                
                {$_ -ge 70} {
                    
                    $popText = 'Extremely likely'
                    
                }
                
            }
            
            Return $popText
            
        }   
        
        {$_ -eq 'alert'}    {
            
            Switch ($curAlerts.type) {
                
                'HEA' {$typeName = 'Heat Advisory'}
                'TOR' {$typeName = 'Tornado Warning'}
                'TOW' {$typeName = 'Tornado Watch'}
                'WRN' {$typeName = 'Severe Thunderstorm Warning'}
                'SEW' {$typeName = 'Severe Thunderstorm Watch'}
                'WIN' {$typeName = 'Winter Weather Advisory'}
                'FLO' {$typeName = 'Flood Warning'}
                'WAT' {$typeName = 'Flood Watch / Statement'}
                'WND' {$typeName = 'High Wind Advisory'}
                'SVR' {$typeName = 'Severe Weather Statement'}
                'HEA' {$typeName = 'Heat Advisory'}
                'FOG' {$typeName = 'Dense Fog Advisory'}
                'SPE' {$typeName = 'Special Weather Statement'}
                'FIR' {$typeName = 'Fire Weather Advisory'}
                'VOL' {$typeName = 'Volcanic Activity Statement'}
                'HWW' {$typeName = 'High Wind Warning'}
                'REC' {$typeName = 'Record Set'}
                'REP' {$typeName = 'Public Reports'}
                'PUB' {$typeName = 'Public Information Statement'}
                    
            }
                
            Return $typeName
    
        }    
    }
    
}

function Get-LIFXApi {
[cmdletbinding()]
param(
    [string]
    $action = 'setstate',
    [string]
    $state = 'on',
    [string]
    $color = 'white',
    [double]
    $brightness = '0.4'
)

$apiKey          = 'YourLifxApiKey'
$base64Key       =  [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(($apiKey)))
$headers         =  @{Authorization=("Basic {0}" -f $base64Key)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptheader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights/'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

$ninjaLights     = Invoke-RestMethod -headers $headers -Uri $allURL

function Change-LightState {
    [cmdletbinding()]
    param(
        [string]
        $state,
        [string]
        $color,
        [double]
        $brightness,
        [string]
        $selector
    )
    
    $ninjaID  = $ninjaLights.id
    $selector = 'id:' + $ninjaID
    $fullURL  = $baseurl + $selector + '/state'

    $payloadBuilder = "{
                    `"power`": `"$state`",
                    `"color`": `"$color`",
                    `"brightness`" : $brightness 
                    }"

    Write-Host "Changing light to:" -ForegroundColor $foregroundcolor
    Write-Host `t"State     :" $state
    Write-Host `t"Color     :" $color
    Write-Host `t"Brightness:" ($brightness * 100)"%" `n

    $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadBuilder
    
    Write-Host "API status:" -ForegroundColor $foregroundcolor
    Write-Host `t"Light :" $stateReturn.results.label
    Write-Host `t"Status:" $stateReturn.results.status `n
    
    
}

Switch ($action) {
    
    'setstate' { Change-LightState -state $state -color $color -brightness $brightness -selector $selector }
    
    'fluxtest' { 
        
        $originalBrightness = $ninjaLights.Brightness
        $originalColor      = $ninjalights.Color
        $originalState      = $ninjalights.Power
        $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
          
        $i = 0
        
        While ($i -le 20) {
            
            $color              = Get-Random $colors
            [double]$brightness = "{0:n2}" -f (Get-Random 0.99)
 
            Change-LightState -color $color -brightness $brightness -selector $selector -state $state
            Start-Sleep -seconds 1
            $i++
            
        }
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector  
        
    } 
    
    'flashcolor' {
        
        $originalBrightness = $ninjaLights.Brightness
        $originalColor      = $ninjalights.Color
        $originalState      = $ninjalights.Power
        $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
        
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
        Start-Sleep -Seconds 1
                
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
        Start-Sleep -Seconds 1        
        
        Change-LightState -state $state -color $color -brightness $brightness -selector $selector
        Start-Sleep -Seconds 1
        
        Change-LightState -state $originalState -color $colorString -brightness $originalBrightness -selector $selector
                        
    }
}    
    
    
}

Get-Weather

Examples:

.\Get-Weather.ps1 -city houston -forecast hourly -sendEmail $true

And here is the email:

$weather = .\Get-Weather.ps1 -city Chicago -lifx $true

As you can see in the above example, the light will flash red. Then it begins  alternating with the state it was in beforehand, and finally it returns the light to the original state it was in.

More to come!

I've been writing this Get-Weather script for a little while now, and there's more I want to do with it. For now that list is:

  • Clean up the code a bit.
  • Add help nodes.
  • Add more error checking.
  • Find out more ways to utilize both the Weather Underground API and the LIFX API.

In the next post I will detail how I use this script in a scheduled task to send out daily weather emails.

As always, let me know if you have any questions, feedback, or ideas!

-Ginger Ninja

PowerShell: Control your LIFX light!

PowerShell: Control your LIFX light!

LET THERE BE LIGHT!

This post has been updated on 5/18/17 to reflect changes made to the Lifx API!

I stumbled upon the fact that LIFX has an API you can use today. Having found that out I wanted to do it in PowerShell and see what I can do. As it turns out there's a decent amount of things you can do and their API is "limited" to around 1 call per second.

If you would like to get into even more detail, step-by-step, and behind the scenes of how this works, check out this post!

Requirements

To get started with this you'll need...

Getting started

Here's what I did to get started. 

  1. Created a PowerShell script named Get-LifxApi.ps1.
  2. Opened the script up with basic parameters and variables to get started.
  3. Somewhat annoying my girlfriend with the light changing so much  ❤️

Starting code

[cmdletbinding(DefaultParameterSetName='SetState')]
param(
    [Parameter(
        ParameterSetName = "StateSetting"
    )]        
    [ValidateSet('SetState','FlashColor','RandomColors','ListLights')]    
    [string]
    $Action = 'SetState',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('on','off')]
    [string]
    $State = 'on',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('white','red','orange','yellow','cyan','green','blue','purple','pink')]
    [string]
    $Color = 'white',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateRange(0.0,1)]
    [double]
    $Brightness = '0.4',
    [Parameter(
        ParameterSetName = "Toggle"    
    )]    
    [Switch]
    $Toggle
)

$apiKey          = 'YourKeyGoesHere'
$headers         =  @{Authorization=("Bearer {0}" -f $apiKey)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptHeader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

Notes

You'll want to change the $apiKey to match your API key from the LIFX cloud.
The $allURL variable will return all your lights, and then the $baseURL variable is used later when formatting calls to change colors or do other things. $foregroundColor let's you specify a color for some of the Write-Host returns, and $colors is an array of colors currently accepted by the API (and you'll see why it is there later in this post). 

Let's make our first call!

I store the results of my light(s) in the $lifxLights variable.

$lifxLights = Invoke-RestMethod -headers $headers -Uri $allURL -ContentType $acceptheader

And now to write our first function in this script.

This function will allow us to utilize the API's state setting option. I named this function Set-LightState

function Set-LightState { #Begin function Set-LightState
    [cmdletbinding()]
    param(
        [Parameter()]
        [ValidateSet('on','off')]
        [string]
        $state,
        [Parameter()]  
        [string]
        $color,
        [Parameter()]
        [ValidateRange(0.0,1)]
        [double]
        $brightness,
        [string]
        $selector
    )

    if ($lifxLight.Connected) {          

        $fullURL  = "$baseurl/$($lifxLight.id)/state"        
        $payload  = [PSCustomObject]@{

            power      = $state
            color      = $color
            brightness = $brightness

        }

        $payloadJson = $payload | ConvertTo-Json

        Write-Host "Attempting to Change light to:" -ForegroundColor $foregroundcolor
        Write-Host `t"State     :" $state
        Write-Host `t"Color     :" $color
        Write-Host `t"Brightness:" ($brightness * 100)"%" `n

        $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadJson -ContentType $acceptheader
    
        Write-Host "API status:" -ForegroundColor $foregroundcolor
        Write-Host `t"Light :" $stateReturn.results.label
        Write-Host `t"Status:" $stateReturn.results.status `n
    
    } else {
        
        $lightName = $lifxLight.label
        Write-Host "$lightName is offline or unreachable :("
        
    }    

} #End function Set-LightState

I only have one LIFX light. In the start of this function I set my 'selector' (a required field for API calls to LIFX when setting states) as the light's ID.  I then use the value of light's ID to setup the URL structure for the call. $fullURL becomes the URL used when accessing the API to set the state of the light.

Let's take some action!

At the start of the script I have a parameter for action. 
Below is how it is used, in conjunction with toggle.

if ($toggle) { #If we're just toggling
             
    $fullURL  = "$baseurl/$($lifxLight.id)/toggle"  
    $toggleResult = Invoke-RestMethod -Uri $fullURL -Method Post -ContentType $acceptHeader -Headers $headers

    if ($toggleResult.results.status -eq 'ok') {

        Write-Host "Light [$($toggleResult.results.label)] was toggled!"

    } else {

        Write-Host "Something went wrong: [$($toggleResult.results.status)]"
    }

} else { #Else we perform the actions!

    Switch ($action) { #Begin switch for script actions
        
        'SetState' {         
            
            Set-LightState -state $state -color $color -brightness $brightness

        }    
        
        'ListLights' {
            
            return $lifxLight
            
        }       

        'RandomColors' { 
            
            $originalBrightness = $lifxLight.Brightness
            $originalColor      = $lifxLight.Color
            $originalState      = $lifxLight.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
            
            $i = 0
            
            While ($i -le 10) {
                
                $color              = Get-Random $colors
                [double]$brightness = "{0:n2}" -f (Get-Random -Maximum 1 -Minimum 0.00)
    
                Set-LightState -color $color -brightness $brightness -selector $selector -state $state
                Start-Sleep -seconds 1
                $i++
                
            }
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness

        }
        
        'FlashColor' {
            
            $originalBrightness = $lifxLights.Brightness
            $originalColor      = $lifxLights.Color
            $originalState      = $lifxLights.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
            Start-Sleep -Seconds 1
                    
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness 
            Start-Sleep -Seconds 1        
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
                            
        }    
    
    } #End switch for light actions
}

My favorite action is the RandomColors. I have that set to use Get-Random to set the color and brightness randomly.  The other action is setstate. What that will do is set the light to a state you specify. If you do not give it options it will default to turning the light on to a brightness of 40% (0.4) and the color value of white (this is defined as per the default options for the parameters at the start of this script). You can change them by supplying the arguments when you run the script.

$fullURL example contents:

https://api.lifx.com/v1/lights/az0321123abc/state

Examples

.\Get-LifxAPI.ps1 -Action setstate -State on -Color blue -Brightness 0.5
lifx.PNG

Did it work?! 
(Yup)

.\Get-LifxAPI.ps1 -Action setstate

The above example is the simplest way to run it as it utilizes the default parameters. (actually, you could just run Get-LifxAPI.ps1)

Now for some fun!

.\Get-LifxAPI.ps1 -Action RandomColors

More to come!

I will be adding to this as I work on it more and clean it up. I will get adding:

  • Help nodes for Get-Help (done!).
  • More options to leverage different parts of the LIFX API (coming).
  • And more as I think of cool things to do with this!

Use:

Get-Help .\Get-LifxAPI.ps1 -Detailed

To see the help that is included. Be sure to change Get-LifxAPI.ps1 to what you named your script to!

The Code

<#
.SYNOPSIS   
    Use this script to control your Lifx light via PowerShell!
.DESCRIPTION 
    You can use this script to turn your light on and off, as well as change the brightness and colors.
.PARAMETER Action

    Argument: The action you'd like to take:
    SetState, FlashColor, RandomColors, and ListLights are valid actions.

.PARAMETER State
    This parameter accepts the state you'd like to set: on or off.
.PARAMETER Color
    Argument: The color you'd like to set the light to. 
    Valid colors can be tab completed.
.PARAMETER Brightness
    Argument: The brightness you want to set.
    Valid range: between 0-1 (0.5 being 50%)  
.PARAMETER Toggle
    Toggles the light      
.NOTES   
    Name: Get-LifxAPI.ps1
    Author: Mike Roberts aka Ginger Ninja
    DateCreated: 2/6/2016
    Last Modified: 5/18/2017

.EXAMPLE   
    $response = .\Get-LifxAPI.ps1 -Action ListLights
    ---------------------------------------------------------------

    1. Get an object returned that contains the result of the API call
    
    p$[18:52:20]> $response
    id                 : nun-ya
    uuid               : more nun-ya
    label              : Ninja room
    connected          : True
    power              : on
    color              : @{hue=249.9977111467155; saturation=0; kelvin=3400}
    brightness         : 0.48508430609597925
    group              : @{id=nun-ya; name=My Room}
    location           : @{id=nun-ya; name=My Home}
    product            : @{name=Original 1000; identifier=lifx_original_a21; company=LIFX; capabilities=}
    last_seen          : 2017-05-19T01:51:49Z
    seconds_since_seen : 32

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Action RandomColors
    ---------------------------------------------------------------

    1. Light toggles between random colors 10 times

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Toggle
    ---------------------------------------------------------------

    1. Toggles light state (on or off respectively)

.EXAMPLE   
    .\Get-LifxAPI.ps1 -Action SetState -State on -Color blue -Brightness 0.5
    ---------------------------------------------------------------

    1. Turns light on
    2. Changes color to blue
    3. Changes brightness to 0.5
.OUTPUTS
    If you use ListLights as the action, the output will be an
    object containing the results of the api call.

.LINK  
    http://www.gngrninja.com/script-ninja/2016/2/6/powershell-control-your-lifx-light
#>
[cmdletbinding(DefaultParameterSetName='SetState')]
param(
    [Parameter(
        ParameterSetName = "StateSetting"
    )]        
    [ValidateSet('SetState','FlashColor','RandomColors','ListLights')]    
    [string]
    $Action = 'SetState',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('on','off')]
    [string]
    $State = 'on',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateSet('white','red','orange','yellow','cyan','green','blue','purple','pink')]
    [string]
    $Color = 'white',
    [Parameter(
        ParameterSetName = "StateSetting"
    )]    
    [ValidateRange(0.0,1)]
    [double]
    $Brightness = '0.4',
    [Parameter(
        ParameterSetName = "Toggle"    
    )]    
    [Switch]
    $Toggle
)

$apiKey          = 'YourKeyGoesHere'
$headers         =  @{Authorization=("Bearer {0}" -f $apiKey)}
$allURL          = 'https://api.lifx.com/v1/lights/all' 
$acceptHeader    = 'application/json'
$baseURL         = 'https://api.lifx.com/v1/lights'
$foregroundColor = 'white'
[array]$colors   = @('white','red','orange','yellow','cyan','green','blue','purple','pink')

function Set-LightState { #Begin function Set-LightState
    [cmdletbinding()]
    param(
        [Parameter()]
        [ValidateSet('on','off')]
        [string]
        $state,
        [Parameter()]  
        [string]
        $color,
        [Parameter()]
        [ValidateRange(0.0,1)]
        [double]
        $brightness,
        [string]
        $selector
    )

    if ($lifxLight.Connected) {          

        $fullURL  = "$baseurl/$($lifxLight.id)/state"             
        $payload  = [PSCustomObject]@{

            power      = $state
            color      = $color
            brightness = $brightness

        }

        $payloadJson = $payload | ConvertTo-Json

        Write-Host "Attempting to Change light to:" -ForegroundColor $foregroundcolor
        Write-Host `t"State     :" $state
        Write-Host `t"Color     :" $color
        Write-Host `t"Brightness:" ($brightness * 100)"%" `n

        $stateReturn = Invoke-RestMethod -headers $headers -uri $fullURL -Method Put -Body $payloadJson -ContentType $acceptheader
    
        Write-Host "API status:" -ForegroundColor $foregroundcolor
        Write-Host `t"Light :" $stateReturn.results.label
        Write-Host `t"Status:" $stateReturn.results.status `n
    
    } else {
        
        $lightName = $lifxLight.label
        Write-Host "$lightName is offline or unreachable :("
        
    }    

} #End function Set-LightState

#Get Lifx Lights
$lifxLights = Invoke-RestMethod -headers $headers -Uri $allURL -ContentType $acceptheader
if ($lifxLights.Count -gt 1) {

    Write-Host "Pick a light:"`n
    for ($i = 0;$i -le $lifxLights.Count - 1;$i++) {

        Write-Host "[$i] -> $($lifxLights[$i].label)"

    }

    $picked = $false

    Do {
        [int]$number = Read-Host "Which [#]?"
        Write-Host "$number"
        if (![String]::IsNullOrEmpty($number) -and ($number -le ($lifxLights.Count - 1) -and $number -gt -1)) {

            $picked    = $true
            $lifxLight = $number  
            write-Host "sup"

        }
    } 
    While ($picked -eq $false)

} else {

    $lifxLight = $lifxLights[0]

}

if ($toggle) { #If we're just toggling
             
    $fullURL  = "$baseurl/$($lifxLight.id)/toggle"  
    $toggleResult = Invoke-RestMethod -Uri $fullURL -Method Post -ContentType $acceptHeader -Headers $headers

    if ($toggleResult.results.status -eq 'ok') {

        Write-Host "Light [$($toggleResult.results.label)] was toggled!"

    } else {

        Write-Host "Something went wrong: [$($toggleResult.results.status)]"
    }

} else { #Else we perform the actions!

    Switch ($action) { #Begin switch for script actions
        
        'SetState' {         
            
            Set-LightState -state $state -color $color -brightness $brightness

        }    
        
        'ListLights' {
            
            return $lifxLight
            
        }       

        'RandomColors' { 
            
            $originalBrightness = $lifxLight.Brightness
            $originalColor      = $lifxLight.Color
            $originalState      = $lifxLight.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin       
            
            $i = 0
            
            While ($i -le 10) {
                
                $color              = Get-Random $colors
                [double]$brightness = "{0:n2}" -f (Get-Random -Maximum 1 -Minimum 0.00)
    
                Set-LightState -color $color -brightness $brightness -selector $selector -state $state
                Start-Sleep -seconds 1
                $i++
                
            }
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness

        }
        
        'FlashColor' {
            
            $originalBrightness = $lifxLights.Brightness
            $originalColor      = $lifxLights.Color
            $originalState      = $lifxLights.Power
            $colorString        = "hue:" + $originalcolor.hue + " saturation:" + $originalcolor.saturation + " kelvin:" + $originalColor.Kelvin
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
            Start-Sleep -Seconds 1
                    
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness 
            Start-Sleep -Seconds 1        
            
            Set-LightState -state $state -color $color -brightness $brightness
            Start-Sleep -Seconds 1
            
            Set-LightState -state $originalState -color $colorString -brightness $originalBrightness
                            
        }    
    
    } #End switch for light actions
}

Leave comment if you have any ideas or feedback!

-Ginger Ninja

PowerShell: Fun with Weather Underground's API (part 1)

PowerShell: Fun with Weather Underground's API (part 1)

Free APIs can be fun!

After doing some work with the Victor OPs API, I personally wanted to see what else was out there. I haven't messed with APIs too much in the past, but now I'm all about it. I'm a bit of a weather geek so I was excited when I found out that Weather Underground has one available for free!

What I've done so far

So far I've created a script that can:

  • Email you an HTML email with the following:
    • Hourly/4 day weather forecast
    • Current (randomly selected) webcam shot from the city you specified
    • Radar animated gif
  • Email a Squarespace gallery with a random camera shot from the city you specify.
  • Return (in PowerShell) the forecast for the city you specify

I'm thinking of things to add to it all the time now... like perhaps an alert check on an interval that sends you a text if there is a weather alert.

I'm doing all this to learn the ins and outs of handling APIs with PowerShell, as well as to feed my inner weather and script geek.

Getting started

This post will be a multi part post. For this portion I will stick to the part that you don't even need and API key for!  (Although, you may want to grab one, here)

Requirements

You'll need to setup the following variables:

  • $apiKey (Can be blank now or just 'yourAPIKeyHere') as it is not actually needed yet.
  • $city (Specify a city you'd like to look up using their free autocomplete API)
  • $baseURL  = 'http://api.wunderground.com/api/'

The Code

$city    = Read-Host "City?"
$apiKey  = 'yourAPIKeyHere' 
$baseURL = 'http://api.wunderground.com/api/'

   $findMe = $city
    $find   = Invoke-RestMethod -Uri "http://autocomplete.wunderground.com/aq?query=$findMe"
    
    if ($find) {
        
        $cityAPI  = $find.Results[0].l
        $city     = $find.Results[0].name
        
        $fullURL  = $baseURL + $apiKey + "/features/conditions/hourly/forecast/webcams/alerts" + "$cityAPI.json"
        $radarURL = "http://api.wunderground.com/api/$apiKey/animatedradar/animatedsatellite" + "$cityAPI.gif?num=6&delay=50&interval=30"
        
        Write-Host `n"API URLS for $city" -foregroundcolor $foregroundColor
        Write-Host `t$fullURL
        Write-Host `t$radarURL

}

Results / Going forward

If you put the above code in a script and run it, the results will be the API URLs it found for the first city it returns. If you want to narrow down it for a different $city, you'll need to specify 'City, State'.

Here are the results for $city = 'Portland'

If you want to get a jump start on this and you have your API key, check out the API documentation from Weather Underground!

Here is a teaser of what can be done (all via PowerShell!):

 

Let me know if you have any ideas or comments!

-Ginger Ninja

PowerShell Quick Tip: Basic use of the Switch statement

PowerShell Quick Tip: Basic use of the Switch statement

Why use Switch?

In PowerShell you can use an if statement to compare things and determine actions based upon the result. You also can use elseif to keep comparing values until you reach a desired (or not so desired) result.

Switch allows you to take a variable you define, and then based upon its value perform different actions.

Example

In this example I will show you a switch statement I used in a script that uses the Weather Underground API to send HTML emails detailing your requested weather forecast. Consider this a teaser until I post that script itself.

What I wanted to do

In this example I wanted to take a returned percentage, and then change a variable to display the appropriate text result. It compares the returned value of the hour's chance of precipitation set in $hourPrecip, and then based on that number changes the variable $popText accordingly.

The Code

Switch ($hourPrecip) {
                        
                        {$_ -lt 20} {
                            
                            $popText = 'No mention'
                            
                        }
                        
                        {$_ -eq 20} {
                            
                            $popText = 'Slight Chance'
                            
                        }
                        
                        {($_ -lt 50 -and $_ -gt 20)} {
                            
                            $popText = 'Chance'
                            
                        }
                        
                        {$_ -eq 50} {
                            
                            $popText = 'Good chance'
                            
                        }
                        
                        {($_ -lt 70 -and $_ -gt 50)} {
                            
                            $popText = 'Likely'
                            
                        }
                        
                        {$_ -ge 70} {
                            
                            $popText = 'Extremely likely'
                            
                        }
                        
                    }

So now you display the percentage, as well as its correlating text value which describes what the percentage means.

If the value was 51 for $hourPrecip, then $popText will be set to Likely

The Weather Underground post will be coming soon!

Do you use switches in your scripts, and if so, how do you like to use them?

PowerShell: Using the VictorOps REST API and PRTG Sensor Output

PowerShell: Using the VictorOps REST API and PRTG Sensor Output

What's it do?

I utilized the VictorOps REST API with PowerShell to return data in a user readable format, or to use with PRTG sensors.

I wanted a way to display who was currently on call via a PRTG map that other users can publicly access.

Note: This is something I wrote in a day, and it will be evolving into a cleaner, error checked format!

What you'll need

Parameters

-getInfo

  • ack               = List/ack any outstanding alerts. Will prompt for message and confirm before acknowledging.
  • OnCall         = List who is currently on call (must specify team with -team parameter) (compatible with -format parameter and PRTG sensors)
  • UserSched  = Get a user's oncall schedule. Currently best to return this into your own variable for now. (Must specify -user parameter)
  • Upcoming   = See who is on call for a team in the future. (must specify team with -team parameter)
  • Incident       = List all incidents (compatible with -format parameter and PRTG sensors)

-team

  • Specify the name of the team. If you have not setup the switch information later in this script, do so to ensure it lines up.
     

-user

  • Specify the username you're getting info for.

-format

  • Specify 'prtg' for certain -getInfo parameters and it will dump it as PRTG sensor information. Leave blank or specify 'user' to return a human readable response. Use 'raw' to return the raw API data. It would be best to call this script into a variable when doing this. $rawAPI = .\Script-Name.ps1 -getInfo 'oncall' -team 'teamname' -format 'raw' 

Examples

Here is some example output.

 .\Get-VictorOpsInfo.ps1 -getInfo incidents
.\Get-VictorOpsInfo.ps1 -getInfo incidents -format prtg

Setting it up

You'll need your API Key and ID from VictorOps. Once you have that, be sure to set them in the script.

$apiKey = ''
$apiID= ''

You can generate a key in VictorOps by going to "Settings -> API."

Be sure to change this switch to match your team setup in VictorOps.

Switch ($team) {

{$team -like "*team1*"}{

$teamName ='team1name'

}

{$team -like "*team2*"} {

$teamName = 'team2name'

}

}

Your username will be set to the username you're logged into the machine with. This is important to note as it sends username when you use the script to ack alerts. To change this, edit the following (you'll want to do this if your username does not match the one in VictorOps):

$ackUser = (Get-ChildItem ENV:\USERNAME).Value 

PRTG Setup

To use this and report info into PRTG, setup the script and ensure Quest AD PowerShell tools are installed on the PRTG machine. 

  1. Drop the script in your Custom Sensor folder (Example: D:\PRTG Network Monitor\Custom Sensors\EXEXML\)
  2. Setup an "EXE/Script Advanced" sensor on PRTG and name it something like "VictorOps Incidents". Select the script in the drop-down.
  3. In the settings specify the following parameters: -getInfo incidents -format PRTG

 

You can also setup a sensor for team on call reporting.
To do this, perform the above steps, but specify the parameters -getInfo OnCall -team unix -format prtg. 
 

That will return a sensor that returns a text message of who is on call with their phone number (pulled from AD).

You can then create a map in PRTG of who is on call that can be provided publicly. To get the on call info use the "Status Icons -> Sensor Message only" Properties in the PRTG map builder.

Scanning Interval

Be sure to change the scanning interval in PRTG to something that makes sense. There probably isn't a reason to keep it at every minute, so change it!


The code

<#   
.SYNOPSIS   
   This script utilizes the VictorOps API to return requested information.
.DESCRIPTION 
   This script can be used in various ways. This implementation returns data and interacts with the API to ack alerts. 
   It can also return values which can be used by PRTG sensors.
   
   Variable structure:
    $apiKey       = Your Victor OPs API Key   
    $apiID        = Your Victor OPs API ID
    $baseURL      = The base URL for the VictorOPs API. You shouldn't need to change this. 
    $acceptheader = "application/json" - this default should be fine
    
    The below information is gathered using the above variables.
    
    $headers = @{ 
    'Accept'       = $acceptheader
    'X-VO-Api-Id'  = $apiID
    'X-VO-Api-Key' = $apiKey    
    }
    
    For more info on the VictorOps API, visit https://portal.victorops.com/public/api-docs.html#/.
.PARAMETER getInfo
    Specify the information you'd like returned or action to take.
    
    ack       = List/ack any outstanding alerts
    OnCall    = List who is currently on call (must specify team with -team parameter) (compatible with -format parameter and PRTG sensors)
    UserSched = Get a user's oncall schedule. Best to return this into your own variable for now. (Must specify -user parameter)
    Upcoming  = See who is on call for a team in the future. (must speficy team with -team parameter)
    Incident  = List all incidents (compatible with -format parameter and PRTG sensors)
 
.PARAMETER team
    Specify the name of the team. If you have not setup the switch information later in this script, do so to ensure it lines up.
    
.PARAMETER user
    Specify the username you're getting info for.

.PARAMETER format
    Specify 'prtg' for certain -getInfo parameters and it will dump it as PRTG sensor information.
    Leave blank or specify 'user' to return a human readable response.
    Use 'raw' to return the raw API data. It would be best to call this script into a variable when doing this. $rawAPI = .\Script-Name.ps1 -getInfo 'oncall' -team 'teamname' -format 'raw' 
    
.NOTES   
    Name: Get-VictorOpsInfo.ps1
    Author: Ginger Ninja (Mike Roberts)
    DateCreated: 1/28/16
.LINK  
    http://www.gngrninja.com/script-ninja/2016/1/28/powershell-using-the-victorops-rest-api   
.EXAMPLE   
    .\Get-VictorOpsInfo.ps1 -getInfo OnCall -team unix
 .Example
    .\Get-VictorOpsInfo.ps1 -getInfo ack
#> 
[cmdletbinding()]
param(
    [string]
    $team,
    [string]
    $getInfo = 'notset',
    [string]
    $user,
    [string]
    $format = 'user'
)

if (!((Get-PSSnapin -name "Quest.ActiveRoles.ADManagement" -ea SilentlyContinue).name -eq "Quest.ActiveRoles.ADManagement")) {
  
        Write-Host `n"Loading Quest Active Directory Tools Snapin..."`n -ForegroundColor $foregroundColor
     
        Add-PSSnapin Quest.ActiveRoles.ADManagement | Out-Null
    }  if(!$?) {

        Write-Host `n"You need to install Quest Active Directory Tools Snapin from http://software.dell.com/products/activeroles-server/powershell.aspx"`n -ForegroundColor Red

        Start-Process "http://software.dell.com/products/activeroles-server/powershell.aspx"
        Break;
}

$scriptName   = $myInvocation.MyCommand
$path         = Split-Path -Path $MyInvocation.MyCommand.Path
$apiKey       = 'yourAPIKey'
$apiID        = 'Your API ID'
$baseURL      = 'https://api.victorops.com' 
$acceptheader = "application/json"

$headers = @{
    'Accept'       = $acceptheader
    'X-VO-Api-Id'  = $apiID
    'X-VO-Api-Key' = $apiKey
}

function Get-OnCallSchedule {
    [cmdletbinding()]
    param(
        [string]
        $baseURL,
        [string]
        $onCallURL
    )
    

    $fullURL = $baseURL + $onCallURL
    
    if ($fullURL) {
        
        $onCallSchedule = Invoke-RestMethod $fullURL -Headers $headers
        
    }
    
    return $onCallSchedule
    
}

function Get-Incident {
    [cmdletbinding()]
    param($baseURL)
    
    $incidentURL     = '/api-public/v1/incidents'
    $fullURL         = $baseURL + $incidentURL
    $onCallIncidents = (Invoke-RestMethod $fullURL -Headers $headers).Incidents

    Return $onCallIncidents
    
}

function Resolve-Incident {
    [cmdletbinding()]
    param ($baseURL)

    $incidents = Get-Incident $baseURL
    
    $i = 0
    #Switch for current phase?
    foreach ($in in $incidents) {
        
        if ($in.currentPhase -like 'UNACKED') {
            
            $i++
            
            $ackURL  = "/api-public/v1/incidents/ack"
            
            $fullURL = $baseURL + $ackURL
            
            Write-Host $in.EntityDisplayName
            Write-Host $in.incidentNumber
            
            $inName = $in.EntityDisplayName
            $inNum  = $in.incidentNumber
            
            Write-Host $fullURL
            
            if ((Read-Host "Ack this alert?") -like "*y*") {       
    
                $ackUser = (Get-ChildItem ENV:\USERNAME).Value  
                $ackMsg  = Read-Host "Ack message?"    
                $outputString = $null
                $outputString = "{
                `"userName`": `"$ackUser`",
                `"incidentNames`": [
                `"$inNum`"
                ],
                `"message`": `"$ackMsg`"
                }"

                Invoke-RestMethod -URi $fullURL -Method Patch -contentType "application/json" -Headers $headers -body $outputString
            
            }
           
            } elseif ($in.currentPhase -like 'ACKED') {
                
                $i++
                
                $ackURL  = "/api-public/v1/incidents/resolve"
                
                $fullURL = $baseURL + $ackURL
                
                Write-Host $in.EntityDisplayName
                Write-Host $in.incidentNumber
                
                $inName = $in.EntityDisplayName
                $inNum  = $in.incidentNumber
                
                if ((Read-Host "Resolve this alert?") -like "*y*") {       
        
                    $ackUser = (Get-ChildItem ENV:\USERNAME).Value  
                    $ackMsg  = Read-Host "Resolution message?"    
                    $outputString = $null
                    $outputString = "{
                    `"userName`": `"$ackUser`",
                    `"incidentNames`": [
                    `"$inNum`"
                    ],
                    `"message`": `"$ackMsg`"
                    }"

                    Invoke-RestMethod -URi $fullURL -Method Patch -contentType "application/json" -Headers $headers -body $outputString
                 
                } 
           }   
    }
    
    if ($i -eq 0) { Write-Host "No alerts to ack or resolve!" }
    
}


Switch ($team) {
  
    {$team -like "*team1*"}  {
        
        $teamName ='team1fullname'
    
    }

    {$team -like "*team2*"} {
        
        $teamName = 'team2fullname'
    
    }  
    
}

Switch ($getInfo) {
    
    {$_ -like "OnCall"} {
       
        if (!$team) {Write-Host `n"Team not specified!"`n -foregroundcolor Red;break}
        
        $onCallURL      = "/api-public/v1/team/$teamName/oncall/schedule"
        $onCallSchedule = Get-OnCallSchedule $baseurl $oncallurl  
        
        if (!$onCallSchedule.Schedule.overrideOnCall) {
    
            $onCallUser     = Get-QADuser $onCallSchedule.Schedule.onCall
           
        } else {
            
             $onCallUser     = Get-QADuser $onCallSchedule.Schedule.overrideOnCall
            
        }        
        
        if ($onCallUser) {
           
            $name   = $onCallUser.Name
            $mobile =  $onCalluser.MobilePhone
        
            Switch ($format) {
         
                {$_ -eq 'user'} {
                 
                    Write-Host `n"Currently on call for team: $team"
                    Write-Host $name "($mobile)"`n
                 
                }
             
                {$_ -eq 'prtg'} {
             
                    Write-Host "<prtg>"                     
                    Write-Host
                    "<result>"
                    "<channel>Team: $team</channel>"
                    "<value>1</value>"
                    "</result>" 
                    "<text>$name ($mobile)</text>"
                    Write-Host "</prtg>"
                    
                }
                
                {$_ -eq 'raw'} {
             
                    Return $onCallSchedule
                    
                }           
             }
         
         }
    }  
  
  {$_ -like "*Upcoming*"} {

        if (!$team) {Write-Host `n"Team not specified!"`n -foregroundcolor Red;break}
        
        $onCallURL      = "/api-public/v1/team/$teamName/oncall/schedule"
        $onCallSchedule = Get-OnCallSchedule $baseurl $oncallurl  
        $upcoming       = $onCallSchedule.schedule.rolls
        
        $upcoming | ForEach-Object{$WeekOf = $_.change.SubString(0,10);$Who = (Get-QADUser $_.OnCall).Name; Write-Host $WeekOf $Who}
          
  } 
  
  {$_ -like "*incidents*"} {
      
        $incidents = Get-Incident $baseURL
        #Maybe make this a switch...
        $unAcked   = $incidents | Where-Object{$_.currentPhase -eq 'UNACKED'}
        $unRes     = $incidents | Where-Object{$_.currentPhase -eq 'ACKED'}
        $resAlerts = $incidents | Where-Object{$_.currentPhase -eq 'RESOLVED'}
        
        if ($unAcked) {
            
            $counta = 1
            if ($unAcked.Count) {$counta = $unAcked.Count}
            $texta    = $unAcked.entityDisplayName 
          
        } else {$counta = 0;$texta = "No alarms in VictorOps!" }
        
        if ($unRes) {
            
            $countr = 1
            if ($unRes.Count) {$countr = $unRes.Count}
            $texta    = "Alert list: " + $unRes.entityDisplayName 
          
        } else {$countr = 0}  
              
        if ($resAlerts) {
       
            $countre = 1
            if ($resAlerts.Count) {$countre = $resAlerts.Count} 
          
        } else {$countre = 0}          
        
        Switch ($format) {
            
            {$_ -eq 'prtg'} {
                
                Write-Host "<prtg>"    
                                 
                Write-Host
                "<result>"
                "<channel>Unacknowledged Alerts</channel>"
                "<value>$counta</value>"
                "</result>" 
                "<text>$texta</text>"
            
                Write-Host
                "<result>"
                "<channel>Unresolved Alerts</channel>"
                "<value>$countr</value>"
                "</result>" 
                "<text>$textr</text>"
        
                Write-Host
                "<result>"
                "<channel>Resolved Alerts</channel>"
                "<value>$countre</value>"
                "</result>" 
                "<text>$textre</text>"
                
                Write-Host "</prtg>"        
                     
            }
            
            {$_ -eq 'user'} {
                
                Write-Host `n"Unacknowledged Alerts" 
                Write-Host `t$counta `n -foregroundcolor Red
                
                Write-Host "List:"`n
                
                foreach ($alert in $unAcked) {
                
                   Write-Host `t $alert.entityDisplayName `n
                
                }                
                
                Write-Host "Unresolved Alerts" 
                Write-Host `t$countr `n -foregroundcolor Red

                Write-Host "List:"`n
                
                foreach ($alert in $unRes) {
                
                   Write-Host `t $alert.entityDisplayName `n
                
                }

                
                Write-Host "Resolved Alerts" 
                Write-Host `t$countre`n -foregroundcolor Green
                
                Write-Host "List:"`n
                
                foreach ($alert in $resAlerts) {
                
                   Write-Host `t $alert.entityDisplayName `n
                
                }
            }
            
            {$_ -eq 'raw'} {
                
                Return $incidents 
             
            }            
            
        }

        
  }
  
  {$_ -like "*usersched*"} {
      
        if ($user) {
      
            $onCallURL      = "/api-public/v1/user/$user/oncall/schedule"
            $onCallSchedule = Get-OnCallSchedule $baseurl $oncallurl
            Return $onCallSchedule

        } else {Write-Host `n"User not specified!"`n -foregroundcolor Red}
  }
  
  {$_ -like "ack"} {
      
      Resolve-Incident $baseURL
      
  }
   
  {$_ -eq 'notset'} {
      
      Write-Host `n"Please specify the action you'd like to take via the -getInfo parameter" -foregroundColor Red
      Write-Host "For help type Get-Help $path\$scriptName"`n
      
  } 
                    
}

Have any ideas on how to use this, or general feedback? Leave a comment!