Cisco CUCM listphone API Call, in detail

In the last post I demonstrated the phone copy application and how it works.

In this post I’ll detail the step by step process on how I developed the initial description and device pool searches for the application section shown in the image below. Starting with using the Cisco Schema reference, then testing with the Postman tool and finally programing the VBA code.

Cisco Schema Reference:

The first step to discovering how to get what we need from the Cisco Call Manager. Either a Web search or from the schema reference. I’m no expert on using the schema, but I’ll go into a bit of detail this one time.

I discovered that I need to use the listphone API call against the CUCM to list the matched phones for the description or device pool app searches. There are hundreds of API calls listed on the schema page, I searched the page for the exact match listphone with 20 results, the result I am looking for is shown in amber below.

All of the below schema images are clickable links.

Clicking the listphone link shows the general settings for the API call.

It has a searchCriteria, which shows the options that we can use to search, and a returnedTags, which is where we specify what we want returned with a successful match.

Clicking the searchCriteria shows we can search by the Device name, description, protocol, CSS, Device pool and the security profile name.

We are interested in the description and the device pool options, since they are the two search options in our application.

Next, clicking on the returnedTags link shows all the data we can return with each phone. There are over 100 items that can be returned, you can click the image for the full list. I’m only showing the top few, which happens to include the options we are looking for:

We need to return the name, description and model to fill in these spaces on the search app:

Postman tool:

Now that we know how to use the API call, it’s time to load it into the Postman tool and send it to the CUCM. I’m not going into details on how to setup and configure the tool, here is a link for that.

Below are the proper SOAP AXL format for the description and device pool searches.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/14.0">
    <soapenv:Header/>
    <soapenv:Body>
        <ns:listPhone>
            <searchCriteria>
                <description>%jane doe%</description>
            </searchCriteria>
            <returnedTags>
                <name></name>
                <model></model>
                <description></description>
            </returnedTags>
        </ns:listPhone>
    </soapenv:Body>
</soapenv:Envelope>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.cisco.com/AXL/API/14.0">
    <soapenv:Header/>
    <soapenv:Body>
        <ns:listPhone>
            <searchCriteria>
                <devicePoolName>tbr%</devicePoolName>
            </searchCriteria>
            <returnedTags>
                <name></name>
                <model></model>
                <description></description>
            </returnedTags>
        </ns:listPhone>
    </soapenv:Body>
</soapenv:Envelope>

We are using ‘jane doe’ and ‘tbr’ for our test searches, like in the app demo video.

The below image shows both the ‘jane doe’ description search and the xml results within the Postman tool.

The next image shows the device pool XML file result for ‘tbr’, opened with Internet Explorer. It lists 6 phones and the three returned tags per phone.

We have now successfully tested and verified how the listphone description and device pool search works through the API interface. On to coding!

VBA code: Connecting to the CUCM

The below code shows how the CUCM request are made with VBA.

First it validates that the user entered at least three characters into the search box. I didn’t want any accidental downloading of every single phone into the app.

The SOAP AXL code sent to the server is assembled line by line with the sENV = sENV & lines. The results should be a comparable string to what was tested in the Postman tool. The username and password are not saved in the app, so a box will pop up asking for them.

Sub Desc_Search_Validate()

ActiveWorkbook.Worksheets("Phone Copy").Select
'test to make sure a search parameter of at least three chars before searching
If Len(Range("B4")) >= 3 Then
    Call Desc_Search
Else
    MsgBox "Use at least Three characters to search"
End If

End Sub

Sub Desc_Search()

    ActiveWorkbook.Worksheets("Phone Copy").Select
    Dim sEnv, sURL, Filename As String
    Dim Req As Object
    Dim Resp As New MSXML2.DOMDocument60
    Dim CUCMresults As String
    Dim Row_counter As Integer
    
    
    Set Req = CreateObject("MSXML2.XMLHTTP")
    Set Resp = CreateObject("MSXML2.DOMDocument.6.0")
    
   

    
    sURL = "https://CUCMSERVER:8443/axl/"

    'Prepare for CUCM request
    Req.Open "post", sURL, False
       
    
sEnv = sEnv & "<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:ns=""http://www.cisco.com/AXL/API/14.0"">"
sEnv = sEnv & "    <soapenv:Header/>"
sEnv = sEnv & "    <soapenv:Body>"
sEnv = sEnv & "        <ns:listPhone>"
sEnv = sEnv & "            <searchCriteria>"
sEnv = sEnv & "                <description>" & "%" & Range("B4") & "%" & "</description>"
sEnv = sEnv & "            </searchCriteria>"
sEnv = sEnv & "            <returnedTags>"
sEnv = sEnv & "                <name></name>"
sEnv = sEnv & "                <model></model>"
sEnv = sEnv & "                <description></description>"
sEnv = sEnv & "            </returnedTags>"
sEnv = sEnv & "        </ns:listPhone>"
sEnv = sEnv & "    </soapenv:Body>"
sEnv = sEnv & "</soapenv:Envelope>"


   ' *******send search request to CUCM
    Req.send (sEnv)
    CUCMresults = Req.responseText
    
   
    ' make sure search was good
    If Req.Status <> 200 Then
                SAXL_message = InStr(CUCMresults, "<axlmessage>")
                EAXL_message = InStr(CUCMresults, "</axlmessage>")
                Len_AXL_message = EAXL_message - SAXL_message
                AXL_message = Mid(CUCMresults, SAXL_message + 12, Len_AXL_message - 12)
                'show any error code
                MsgBox "ERROR: " & AXL_message
                Exit Sub

    Else
            'read the device and lines configs since no errors
            Call ListPhoneSearch(CUCMresults)
    End If
    
End Sub

This next line (from the above code), specifies the search criteria, retrieving the search criteria from Excel Range(“B4”) and adding the wild cards before and after the search term. Making this the CUCM equivalent of searching for a phone with a variable description pulled from cell B4 instead of the static search used in the Postman test.

sEnv = sEnv & "    <description>" & "%" & Range("B4") & "%" & "</description>"

The device pool search is identical with the exception of the replacement of the above description line with the below device pool line and with no wild card in front, notice it pulls from cell B5.

sEnv = sEnv & "     <devicePoolName>" & Range("B5") & "%" & "</devicePoolName>"

Now we should have our search results loaded into the variable CUCMresults. There is some validation at the end to make sure the API connection works, before sending it to the XML reader sub.

VBA code Reading the XML results

I’m not a programmer, there is most likely an better way to accomplish this, I welcome any suggestions. I simply take the entire XML string and pull out the data between the two phone tags for each phone, one at a time and read the returned tags for each individual phone, then go to the next phone in the string, until there are no phones left in the XML string.

Sub ListPhoneSearch(CUCMresults)
    
    line_elocation = 100
    Row_counter = 9

    'set so it doesn't skip first phone in the XML string
    lastendofphone = InStr(CUCMresults, "<return>")
    
    ' loop until there no more phones in the XML string
    Do While InStr(lastendofphone, CUCMresults, "<phone uuid") <> 0
       
        'pulls the current phone line between"<phone uuid" and "</phone>"
        startofphone = InStr(lastendofphone, CUCMresults, "<phone uuid")
        endofphone = InStr(lastendofphone, CUCMresults, "</phone>")
        phonestringlen = endofphone - startofphone + 8
        currentphonestring = Mid(CUCMresults, startofphone, phonestringlen)
        
        'retrieve tags from phone string
        'retrive devicename
        tag_startlocation = InStr(currentphonestring, "<name>")
        tag_endlocation = InStr(currentphonestring, "</name>")
        tag_len = tag_endlocation - tag_startlocation - 6
        tagstring = Mid(currentphonestring, tag_startlocation + 6, tag_len)
        Range("A" & Row_counter) = tagstring
        
        'retrive description
        tag_startlocation = InStr(currentphonestring, "<description>")
        tag_endlocation = InStr(currentphonestring, "</description>")
        tag_len = tag_endlocation - tag_startlocation - 13
        tagstring = Mid(currentphonestring, tag_startlocation + 13, tag_len)
        Range("B" & Row_counter) = tagstring
        
        'retrive model
        tag_startlocation = InStr(currentphonestring, "<model>")
        tag_endlocation = InStr(currentphonestring, "</model>")
        tag_len = tag_endlocation - tag_startlocation - 7
        tagstring = Mid(currentphonestring, tag_startlocation + 7, tag_len)
        Range("C" & Row_counter) = tagstring
        
        'sets up for next search results row
        Row_counter = Row_counter + 1

        'sets the counter to the end of the current phone, ready to read the next         phone 
        lastendofphone = endofphone + 8

   Loop
      
            
       Range("B4").Select
            
End Sub

That was a long post, I wanted to get a bit more detailed on the first section, to show the entire process. I won’t get as detailed in the next section.

Leave a comment

Design a site like this with WordPress.com
Get started