Accessing Informacast from Powershell

5 minute read

Singlewire, the makers of Informacast have a very detailed document of the API. It is best to check the Compatibility Matrix for your version of Informacast. The focus is on Informacast Advanced, but most of the following applies to the Informacast Fusion REST API as well.

If you view the Informacast API documentation, there is documentation for many programming languages, but sadly PowerShell has been overlooked. Hopefully the following will help.

Getting an Authentication Header

Informacast API uses the basic authorization standard for authentication. Basic authorization is a user name and password separated by a colon.

The Singlewire documentation has a cURL example for the authorization header:

-H 'Authorization: Basic YWRtaW46Y2hhbmdlTZZ='

This is using an authorization token that appears to be base64 encoded. Let’s check if this is a base64 encoded user:pass string:

[System.Text.Encoding]::Ascii.GetString([System.Convert]::FromBase64String("YWRtaW46Y2hhbmdlTZZ="))
admin:changeM?

Perfect. Now we know this is base64 encoded so let’s create our authorization header for our Powershell script

#Generate Authorization Header

$single_Pass = 'changeM?'
$single_User = 'admin'
$pair = "${single_User}:${single_Pass}"

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64Token = [System.Convert]::ToBase64String($bytes)

$basicAuthValue = "Basic $base64Token"

$headers = @{ Authorization = $basicAuthValue } 

Now that we have the Authorization Header created we can connect to Informacast

Informacast API Explorer

Using the Informacast API Explorer you can view the methods that are available from the API. You can access the API explorer from your Singlewire instance from https://{singlewireaddress}/InformaCast/API_Explorer/

This allows you to view the operations and even try them out to see what gets reported from the API. Let’s try some Basic Administraton tasks before we start adding or removing anything.

Get the BasicAdmin Overview

The Request URL is displayed in the API Explorer when you select Try it out!, copy and paste the URL to your script:

$single_Pass = 'changeM?'
$single_User = 'admin'
$pair = "${single_User}:${single_Pass}"

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64Token = [System.Convert]::ToBase64String($bytes)

$basicAuthValue = "Basic $base64Token"

$headers = @{ Authorization = $basicAuthValue }

Invoke-RestMethod -Uri "http://{singlewireaddress}:443/Informacast/RESTServices/V1/BasicAdmin/overview/" -Headers $headers -Method Get

applicationMode                           : Stand-alone
basicPagingMode                           : False
callingTerminals                          : {}
clusters                                  : {@{provider={singlewireIP}; description=Default configuration; providerIsSecure=False; version=12.5.1.12900-115}}
jtapiVersion                              : Cisco Jtapi version 12.5(1.12900)-2 Release
licensedPhones                            : 1000
multicastPortsConfigured                  : 301
multicastPortsUnused                      : 301
multicastPortsUsedByAudioBroadcasts       : 0
multicastPortsUsedByTalkAndListenMessages : 0
numberOfConfiguredSpeakers                : 2600
numberOfRegisteredSpeakers                : 900
phoneCount                                : 750
phoneRefreshInterval                      : 120
phonesUsedCount                           : 45
routeAddresses                            : {}
sipCallsSnapshot                          : @{snapshot=System.Object[]}
userAgentStartException                   : 
userAgentStatus                           : User Agent is running
backupActivated                           : True
ldapAuthenticationEnabled                 : False
ldapGroupingEnabled                       : False
publishSOAPAPI                            : True
publishSpeakerConfigurationURL            : True
sendCommandsByJtapi                       : True
userAgentStartFailure                     : False
licensedSpeakers                          : 5000
resiliencyInfo                            : {}
slpEnabled                                : True
currentServerTimeGMT                      : 2019-08-10T16:03:15.168+0000
currentServerTimeLocal                    : 2019-08-10T12:03:15.168-0400
nextLDAPRefreshGMT                        : 2019-08-10T16:40:00.000+0000
nextLDAPRefreshLocal                      : 2019-08-10T12:40:00.000-0400
nextScheduledBackupGMT                    : 2020-10-09T07:00:00.000+0000
nextScheduledBackupLocal                  : 2020-10-09T03:00:00.000-0400
phoneRebuildAttemptTimeGMT                : 2019-08-10T05:00:00.001+0000
phoneRebuildAttemptTimeLocal              : 2019-08-10T01:00:00.001-0400
phoneRebuildNextTimeGMT                   : 2020-10-09T05:00:00.000+0000
phoneRebuildNextTimeLocal                 : 2020-10-09T01:00:00.000-0400
phoneRebuildSuccessTimeGMT                : 2019-08-10T05:02:08.974+0000
phoneRebuildSuccessTimeLocal              : 2019-08-10T01:02:08.974-0400
phoneRefreshAttemptTimeGMT                : 2019-08-10T15:06:00.002+0000
phoneRefreshAttemptTimeLocal              : 2019-08-10T11:06:00.002-0400
phoneRefreshSuccessTimeGMT                : 2019-08-10T15:06:01.343+0000
phoneRefreshSuccessTimeLocal              : 2019-08-10T11:06:01.343-0400
startTimeGMT                              : 2019-07-31T15:05:22.937+0000
startTimeLocal                            : 2019-07-31T11:05:22.937-0400
version                                   : 12.15.1 - 85  Purchased license

We got some info back from the API! We know or connection is working, now let’s do something with it.

Get a list of all IPSpeakers

In the API Explorer we can see that /V1/IPSpeakers allows us to get a list of configured IP Speakers, so let’s get the list (I am assuming the Authentication Header is already available in the current session)

$speakerList = Invoke-RestMethod -Uri "http://{singlewireaddress}:443/Informacast/RESTServices/V1/IPSpeakers/" -Headers $headers -Method Get

$speakerList

previous next                                                                         total data                                                                         
-------- ----                                                                         ----- ----                                                                         
         https://singlewire:443/InformaCast/RESTServices/V1/IPSpeakers?startIndex=100  2600 {@{index=0; id=1072; name=Device 1; description=device 1; d...

So now we have the list of ALL IPSpeakers, all 2600 of them. But …WAIT… if we check the count it doesn’t add up

$speakerList.data.Count
100

A little look at the API Explorer, you can see there are some options available to pass along with the request. The one that looks like it can help is maxCount. Let’s set the maxCount to something greater than 2600 to get all the devices.

$parameters = @{maxCount = '3000'}
$speakerList = Invoke-RestMethod -Uri "http://{singlewireaddress}:443/Informacast/RESTServices/V1/IPSpeakers/" -Headers $headers -Body $parameters -Method Get

$speakerList

previous                                                                                  next                                                                                        total data                                                                         
--------                                                                                  ----                                                                                        ----- ----                                                                         
https://singlewire:443/InformaCast/RESTServices/V1/IPSpeakers?maxCount=3000&startIndex=0  https://singlewire:443/InformaCast/RESTServices/V1/IPSpeakers?maxCount=3000&startIndex=1001 2600  {@{index=0; id=1072; name=Device 1; description=device 1; d...

Great we can see that the maxCount of 3000 was set and the total records is 2600. Let’s check the data count again:

$speakerList.data.Count
1000

What gives, 1000!! We specified maxCount to 3000, why did we only get 1000 returned. Well it turns out that API will only return 1000 records maximum, no matter if you specify a greater number for maxCount.

How do we get all the records? Well, we could break down the requests into multiple batches, by dividing the total records into multiple requests and process each. Honestly after messing around with the math needed to do just this, I realized the solution to getting all the records was already returned. The previous and next objects returned from the initial query. Looking at the next data shows that we already got the first 1000 records and there is more still to get. We just have to keep querying the API until we have all the records.

So a full script that gets all the configured speaker devices:


#Get all configured IPSpeakers

$single_Pass = 'changeM?'
$single_User = 'admin'
$pair = "${single_User}:${single_Pass}"

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64Token = [System.Convert]::ToBase64String($bytes)

$basicAuthValue = "Basic $base64Token"

$headers = @{ Authorization = $basicAuthValue }
$parameters = @{maxCount = '1000'}

$overview = Invoke-RestMethod -Uri "http://{singlewireaddress}:443/Informacast/RESTServices/V1/BasicAdmin/overview/" -Headers $headers -Method Get

$total = $overview.numberOfConfiguredSpeakers
$batch = 1000 #maximum number of objects returned from the API

$records = @()  #Array for returned data from API requests

#get the first set of records
$list = Invoke-RestMethod -Uri "http://{singlewireaddress}:443/Informacast/RESTServices/V1/IPSpeakers/" -Headers $headers -Body $parameters -Method Get
$records = $records + $list.data #Append the returned Data to the records array

#if there is any 'next' data, let's get the data and append to the records array
if (!$list.next) {
    do {
        $list = Invoke-RestMethod -Uri $list.next -Headers $headers -Body $parameters -Method Get
        $records = $records + $list.data
        $records.count
    }
    until (
        $list.next -eq $null
    )
}

Now let’s check if we got all the records!

$records.count
2600

Awesome. We now have all the configured IPSpeakers.