Cisco Jabber (CAXL) powered web chat

Cisco IM&Presence server provides the ability to connect to it via BOSH interface. In order to turn this feature on navigate to Cisco Unified IM and Presence Serviceability -> Tools -> Control Center – Feature Services -> choose a node -> Cisco XCP Web Connection Manager and check if it’s started and activated.

Next, check what security setting are applied to it: Cisco Unified CM IM and Presence Administration -> System -> Security -> Settings. If Enable Web Client to IM/P Service Secure Mode is checked you’ll use https to reach BOSH interface, http otherwise.

Now let’s check if BOSH interface is up: navigate to https://cup_server_name:7335/httpbinding (use http if you are not using secure connection). You browser should show something like this:

123123

This URL can be overriden by modifying Cisco Unified CM IM and Presence Administration -> System -> Service Parameters -> choose a node -> Cisco XCP Web Connection Manager -> HTTP Binding Paths Handled – Path field.

I know only 2 clients that support BOSH connections: Pidgin and CAXL, which is a Cisco javascript library. The description of the latter can be found here and library docs here.

I decided to implement web chat, based on this library. The source can be found here. You’ll need Python2 with Flask and  requests modules for it to work.

After launching the app you’ll se a login screen:

login123123123

  • username: full username with domain part, e.g. user@example.com
  • password: end user password
  • IM&P node: FQDN or IP address or IM&P Node with Cisco XCP Web Connection Manager running
  • chat alias: full group chat name in a form like chat_name@chat_alias. Navigate to Cisco Unified CM IM and Presence Administration -> Messagin -> Group Chat Server Aliases  Mapping to check what chat_aliases are available

Once logged in the main window should look like that:

main123123123

The styling is pretty simple and can be modified.

 

 

Video broadcasting and recording with Cisco part 3. TCS API

In part 1 of these series we created two aliases 1001 and 1002 and the first one was used for recording. Cisco TCS has it’s own interface for downloading records and provides opportunity to add description to records (recording aliases to be exact) in order to help you identify then later. TCS is build on Windows so you can add it to your domain controller and authenticate users with it. I don’t have one and don’t like the idea of users even browsing TCS interface so here is a simple Python  class with three methods: first for listing all calls on TCS, second is for adding description before recording and last one for obtaining a list of download URLs for recorded streams.

import urllib2 
from suds.client import Client 
from suds.transport.https import HttpAuthenticated 
from suds import WebFault
from datetime import datetime
import xml.etree.ElementTree as ET
TCS_API_HOSTNAME='192.168.0.10'
TCS_API_URL='/tcs'
TCS_API_USERNAME='admin'
TCS_API_PSW='admin' # do not forget to change API password in TCS management interface
TCS_WSDL='http://'+TCS_API_HOSTNAME+TCS_API_URL+'/Helium.wsdl'
TCS_API_PROXY='http://'+TCS_API_HOSTNAME+TCS_API_URL+'/SoapServer.php'
TCS_API_ROOT='http://'+TCS_API_HOSTNAME+TCS_API_URL
class tcs_api_handler(object):     
    def get_current_cf_list(self):    # getting layout of current calls as aliases with their ids        
        passman = urllib2.HTTPPasswordMgrWithDefaultRealm()        
        passman.add_password(None, TCS_API_ROOT, TCS_API_USERNAME, TCS_API_PSW)        
        authhandler = urllib2.HTTPDigestAuthHandler(passman)        
        opener = urllib2.build_opener(authhandler)        
        res = opener.open(TCS_API_ROOT+'/status.xml')        
        response = res.read()        
        res.close()        
        tree = ET.fromstring(response)        
        cf_list={}        
        for call in tree.iter('{http://www.tandberg.no/XML/CUIL/1.0}Call'):            
            cf_id=call.find('{http://www.tandberg.no/XML/CUIL/1.0}ConferenceId').text            
            alias_full=call.find('{http://www.tandberg.no/XML/CUIL/1.0}SIPURI').text            
            cf_list[alias_full.split("@")[0]]=cf_id        
        return cf_list                           
    def prepair_alias(self, alias,description):        
        t = HttpAuthenticated(username=TCS_API_USERNAME, password=TCS_API_PSW)        
        t.handler=urllib2.HTTPDigestAuthHandler(t.pm)        
        t.urlopener = urllib2.build_opener(t.handler)        
        client = Client(TCS_WSDL, location=TCS_API_PROXY, transport=t)                        
        res=client.service.GetRecordingAlias(Alias=alias)        
        res.RecordingDescription=description        
        try:            
            res1=client.service.ModifyRecordingAlias(Alias=alias, Data=res)            
            return res1        
        except WebFault as err:            
            return err            
    def get_donwloadlink_all(self):        
        t = HttpAuthenticated(username=TCS_API_USERNAME, password=TCS_API_PSW)        
        t.handler=urllib2.HTTPDigestAuthHandler(t.pm)        
        t.urlopener = urllib2.build_opener(t.handler)        
        client = Client(TCS_WSDL, location=TCS_API_PROXY, transport=t)                        
        userparams = {'SearchExpression':'','ResultRange':'','DateTime':'','UpdateTime':'','Owner':'','Category':'','Sort':''}        
        res=client.service.GetConferences(**userparams)        
        res1={}        
        for cf in res[0]:            
            time=datetime.fromtimestamp(int(cf['DateTime']))            
            if cf['HasDownloadableMovie']==True:                
                res1[str(cf['ConferenceID'])]= [unicode(cf['Title']).split('$')[0],str(cf['Description']),str(datetime.fromtimestamp(int(cf['DateTime']))), str(cf['DownloadableMovies'][0][0]['URL'])]             
        return res1

So every time recording alias is added to the conference I issue prepair_alias(‘1001′,’Some descriptions’) and when the recording is done and TCS finished transcoding it I can use  get_donwloadlink_all to list all downloadable movies along with their description, timestamp and alias used for recording.