Cisco Finesse – Adding 3rd Party Gadgets

Hey guys,

In this post, I’m going to show you how to add new gadgets to your Cisco Finesse.
It can be any special gadget you may have created, or even a simple web page to be opened in one of the Finesse Tabs.

Finesse itself allow you to upload third-party gadgets. It’s done via an specific user, 3rdpartygadget. This account only has permission to this directory, /files, and any directories created under it.

  • Set a Third Party Gadget account password

To start off, we need firstly to set a password for this account, via CLI.
So, connect via SSH into your UCCX server and enter the line command: utils reset_3rdpartygadget_password .
For the password, enter ciscocisco,  and confirm it.

image

Not, it’s time to upload your Gadget to the server.
Finesse gadgets are OpenSocial gadgets. An OpenSocial Gadget is an XML document that defines metadata for an OpenSocial Gadget container, the Finesse agent desktop. Gadgets are highly cacheable so it does not need a high-performance server.

A gadget consists of the following:

  • XML to define metadata
  • HTML for markup
  • JavaScript for interactivity
  • CSS for presentation & style

Let’s see now the steps to upload your files. For this task, I’m using FileZilla (download):

  1. Open FileZilla.
  2. In the quickconnect bar,
    in red, fill the following fields:
  • Enter the Finesse FQDN: {{web-url}} in the Host field.
  • Enter 3rdpartygadget in the Username field.
  • Enter ciscocisco in the Password field. This is the 3rdpartygadget password defined in the previous step.
  • Enter 22 in the Port field.
  • Click Quickconnect.

image

  • If a message pops up, about Unknown host key, select Always trust this host, add this key to the cache, and then OK.
  • You must see now a message like that in the log section: Status:     Connected to <URL>.
  • In the remote site section, confirm that you see a folder named / and you can see the files folder below.

image

Now you have to transfer your Gadgets file to the server:

  • Drag the EmbeddedWebApp folder (that contains the xml, js, and css) into the files folder. Note that this is the folder inside of the EmbeddedWebAppSampleGadget-Finesse-x.x.x-vx.x folder.
  • Confirm that the transfer was successful by checking that the transfers shows up in the Successful transfers tab at the bottom.

image

Give the right permission to the files. They have to have public read permission to be loaded o the Finesse Agent Desktop.

  • Select the EmbeddedWebApp folder.
  • Right-click on the EmbeddedWebApp folder.
  • From the dropdown menu, select File permissions….
  • A Change file attributes window appears.
  • Under Public permissions verify that Read permissions is selected.
  • Select Recurse into subdirectories.
  • Click OK.

image

In my case, I’ve added a new Tab to my Finesse, and added my gadget. This gadget opens a URL in my webserver, an it’s used only by Supervisors.

To do that, go to your UCCX, then go to Cisco Finesse Administrator

image

Go to Team Resources, and select the Team you want to change the Layout to include your new Tab/Gadget:

image

In the box below, you see now the Desktop Layout Configuration.
This is how your Finesse will look like, and its gadgets.
First thing you have to do, is to select the option Override System Default. So you can edit the XML.

image

So now, you have to copy all that XML file to a notepad, and add manually the Tab you want to have, and the gadget you just have added.
In my case, I want only Supervisors to have access to it, so in the XML, I go direct to the second block, which is related to Supervisors.

My XML will be like that:

I’ve added 2 Tabs: one called ISR Management, and a second one, TEST

image

After adding the new Tab to your XML, you have to Copy and Paste it back to your Desktop Layout Configuration, and Save it.

Now go back to your Finesse, and you must be able to see the 2 Tabs you just added:

image

In my case, when I select the Tab, it runs a page from my webserver:

image

I hope you like it Smile

See ya!

Bruno

Cisco UCCX – Sending email using Script

Hi people!
In today’s post, I will show you how to configure your UCCX Script to send emails.

This can be easily a complement of my last Post (Cisco UCCX – Recording Prompt Script). In this post, I showed you how to create a script where you can record your own audio prompts and upload them to UCCX. Now, with this post, you can add some steps to send the recorded audio via email to improve a little bit your achievement.

Well, let’s go to the configuration!

Configure Email on UCCX Server
Go to your UCCX,  Subsystem Menu, then Email.
You have to add the SMTP and an email account which will be the source.

image

Variables
You can have as many variables as you want to easy your life. But there is one you must create.
Create a Contact Type variable, give a name,  “EmailContact” in my example, and give a null value.

image

Steps to be used in the Script

  • Create eMail
    Here you generate the subject line and body of the e-mail message.
  • Subject: Variable or expression that you want to use for the subject line of the message.
    Body: Variable or expression that you want to use for the body of the e-mail message
    eMail Contact: Variable that identifies the email. The variable “EmailContact”  we’ve created above.

    image

  • Attach To eMail
    Use the Attach To eMail step to attach a document to an e-mail.
    Before you use an Attach To eMail step, you must use a Create eMail step to create the e-mail message.

    I’m showing you now how to attach that audio prompt we’ve just recorded, as an example.
    In that case, the variable Result contains the recorded audio, and I’m attaching it to the email using this Step.

    image

  • Send eMail
    Use the Send eMail step to send an e-mail message you have created with the Create eMail step.
    When a script reaches the Send eMail step, it immediately sends the e-mail message to the e-mail server, and keeps the client waiting until the message is accepted by the e-mail server. If the server is unavailable because of server or network problems, the client must wait until the transaction times out.

image

So, your code must be like that.

image

It’s a really short code, but the idea is to have that attached to your main script, as a feature, to help you to handle queues, or other things, like sending recorded audios..

Hope you’ve enjoyed!
See ya!

Bruno

Cisco UCCX – Recording Prompt Script

Hey Guys,

Today I’m going to show you the step-by-step to create a Script on UCCX, where you can record your own Audio Prompt. The audio is automatically saved in a Folder on UCCX.

It’s not an advanced Script, but it’s very useful.
Audio will be saved with the User’s ID, plus the date/time. I found this way easy to be found in the Folder, for instance: 1234567_07_19 – 10018am.wav.

Let’s see the steps to create the Script:

  • Defining Date/Time
    We are going to get the current Date and Time, and then, split it into 4 variables: second, minutes, hour, month and day. Then, add then in a variable sSlotTime, which will be part of the name of the Audio.
    These steps Switch are add the “0” in a number. For example, from “1” to “01”, so we keep all with 2 digits. We do the same for day, month, hour, minutes and second (always from 0 to 9).
    For the period, the result will give us 1 or 0. If it’s 1, I set the period to pm. If it’s 0, I set the period to am.

 

imageimage

imageimage

  • Getting User ID
    Now we will ask the user to enter their ID’s. The only reason here is to name the audio according to the ID. If you want, you can ask the user to enter ID and PIN as an authentication.
    You are saving the ID in a variable called ID.
    Then, we are setting the variable sFileType with ID + “_”.

imageimage

image

  • Recording
    Time now to Record the audio. To do that, there is a step called Recording, where you indicate which variable you will save the result, audio, maximum duration, etc..
    So we are saving it in a variable called Result.

image
imageimageimage

  • Manipulating the Result
    After recording the audio(with success), I’m giving 3 options to the user, through a Menu:

image
Press 1 to Listen the recorded audio – The audio saved in the variable Result will be played.
Press 2 to Save – We will give a full name to the audio. Variable sFileName will receive the Folder + sFileType + sSlotTime + “.wav”
Press 3 to Record it again – Go back to the Recording Step

image

  • Authentication
    To be able to save the audio to UCCX, we need authenticate, with an admin credential.
    So firstly, we need to Get the User, then you have to authenticate it.

imageimageimage
image

  • Saving the audio
    After authenticating, we have to save the file in the audio repository.
    We use the step Upload Prompt to send the audio to the Server. If the Upload is done successfully, user will listen to a Menu, asking to press 1 to Record another audio, or any digit to finish.image
    The file name is that variable sFileName we’ve prepared, and the Document is the audio saved in the variable Result.

    image

Basically, this is the code!

YOU CAN NOW DOWNLOAD THE SCRIPT HERE!!
I hope you enjoyed!

See ya!

Bruno

imageimageimage

UCCX – Queries using Python Script

Hey guys,

As promised in my post about ODBC Connection, (you can read it HERE), I’m going to show you how to create a basic Script using Python to query some information from UCCX, which can be useful to create some personalized Dashboards.

Even though we have many types of reports on CUIC, sometime they don’t meet our expectations by having too much unnecessary information or by lack of information.

I’ have decided to use Python, along with HTML, to create my own Dashboard. So I can have only information I know is 100% useful.

First of all, you have to create the ODBC connection to the server where you are going to place the script.
Again, you can use THIS POST to help you out.

Once you have the ODBC Connection working, it’s time to work on your script.

To be able to connect your script to your ODBC, you need to have a PYODBC python Library installed. To be able to better manipulate date and time, I’m also using datetime library.

The first part of the script is used to establish a connection to your ODBC. So you need to fill all its information in the connection strings. It’s important to mention that pyodbc does not even look at the connection string. It is passed directly to the database driver.

To start off my code, I’ll call the libraries and use the command conn = pyodbc.connect to connect to my ODBC.

image

Connection is now ready!
Now it’s time to choose a query to be sent. That query is sent using SQL commands.
This means you can use your SQL skills to play with queries and create interesting reports

Smile

In the below example, I wanted to know how many licenses are being consumed daily.
To do that, I’ll use the SQL command: ” {call sp_license_utilization(‘2021-05-05 00:00:01′,’2021-05-05 23:00:01′,’0′,’1’)}”. The line in the script will be like that:

cursor.execute(” {call sp_license_utilization(‘2021-05-05 00:00:01′,’2021-05-05 23:00:01′,’0′,’1’)}”)

If you print the result, you will see something like that:

[(datetime.datetime(2021, 4, 16, 0, 0, 1), 1, 0, 3), (datetime.datetime(2021, 4, 16, 1, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 2, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 3, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 4, 0, 1), 1, 0, 6), (datetime.datetime(2021, 4, 16, 5, 0, 1), 0, 0, 18), (datetime.datetime(2021, 4, 16, 6, 0, 1), 2, 0, 43), (datetime.datetime(2021, 4, 16, 7, 0, 1), 4, 0, 58), (datetime.datetime(2021, 4, 16, 8, 0, 1), 9, 0, 63), (datetime.datetime(2021, 4, 16, 9, 0, 1), 6, 0, 64), (datetime.datetime(2021, 4, 16, 10, 0, 1), 5, 0, 62), (datetime.datetime(2021, 4, 16, 11, 0, 1), 4, 0, 51), (datetime.datetime(2021, 4, 16, 12, 0, 1), 5, 0, 51), (datetime.datetime(2021, 4, 16, 13, 0, 1), 4, 0, 49), (datetime.datetime(2021, 4, 16, 14, 0, 1), 4, 0, 39), (datetime.datetime(2021, 4, 16, 15, 0, 1), 3, 0, 27), (datetime.datetime(2021, 4, 16, 16, 0, 1), 2, 0, 15), (datetime.datetime(2021, 4, 16, 17, 0, 1), 0, 0, 10), (datetime.datetime(2021, 4, 16, 18, 0, 1), 1, 0, 8), (datetime.datetime(2021, 4, 16, 19, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 20, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 21, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 22, 0, 1), 0, 0, 5), (datetime.datetime(2021, 4, 16, 23, 0, 1), 0, 0, 5)]

Then, use Python to manipulate the results according to your needs. In my case, I’m using the datetime to get today’s date. I also created a list to save the values, as this code will check the license each hour, and give me the maximum as a final result.

The full code for this sample is:

image

 

import pyodbc
from datetime import datetime

conn = pyodbc.connect(‘DRIVER={IBM INFORMIX ODBC DRIVER};’
‘UID=uccxhruser;PWD=123456;’
‘DATABASE=db_cra;’
‘HOST=uccxlab.com;’
‘SERVER=uccxlab_uccx;’
‘SERVICE=1504;PROTOCOL=onsoctcp;CLIENT_LOCALE=en_US.UTF8;DB_LOCALE=en_US.UTF8’)
cursor = conn.cursor()

listItem = []
listLicCCX = []
timestampStr = datetime.now().strftime(“%Y-%m-%d”)

try:
cursor.execute(” {call sp_license_utilization(‘” + str(timestampStr) + ” 00:00:01′,'” + str(timestampStr) + ” 23:59:59′,’0′,’1’)}”)
rows = cursor.fetchall()
LicenseUsage = rows
for hourly in LicenseUsage:
if hourly[3] != None:
listItem.insert(0, hourly[3])
else:
listItem.insert(0, 0)
except pyodbc.Error as ex:
print(“An exception occurred”)
listItem.insert(0, 0)
listLicCCX.insert(0, (max(listItem)))

print(listLicCCX)

And this is the final result:

image

Remember you can use any SQL Query!

For example, this is the SQL query to get a list of Agents by Team:select s.resourceLoginID,s.resourceFirstName,s.resourceLastName,s.extension, t.teamname from Resource s inner join team t on s.assignedTeamID = t.teamid where s.active = ‘t’ and t.active = ‘t’ and t.teamname = ‘UCCX_TEAM’ order by t.teamname, s.resourceloginid

Using a simple Select * from rtcsqssummary here csqname = ‘<CSQ Name>’ query you can display more information as this query will return the following information.

csqname
loggedinagents
availableagents
unavailableagents
totalcalls
oldestcontact
callshandled
callsabandonded
callsdequeued
avgtalkduration
avgwaitduration
longesttalkduration
longestwaitduration
callswaiting
enddatetime
workingagents
talkingagents
reservedagents
startdatetime
convavgtalkduration
convavgwaitduration
convlongestwaitduration
convlongestwaitduration
convoldestcontact

The sky is the limit!

Smile

Now that you now how to use SQL queries in Python, you can start creating your own script!

Enjoy!

Bruno

Cisco Finesse – Disconnection Problems

Hi everybody,

Today,  I’m going to give you a troubleshooting tip about an issue I’ve been facing, on Cisco Finesse.

Agents started complaining that they suddenly get disconnected, and when you see the reports on CUIC, the reason is Connection Failure.

For this case, we are using Cisco UCCX 11.6.2.

First of all, we have to check the Layer 1. Make sure the phone is not losing connection due a cabling faulty.
If you are using Jabber, make sure you network connection is stable, and if it’s VPN, your internet is stable.
Voice traffic is really sensitive, so any minimum interruption can cause a disconnection.

Another thing Cisco recommends is, if your agent has Deskphone and Jabber configured with the same line (but not using at the same time, as UCCX does not support shared lines), you have to keep only one added to the End user and to the Application user. If you have both, it work, but you will have that disconnection some times as well (yes, I faced that in the past).

Now, the latest I’ve heard from them!

As per this Troubleshooting, these presence driven logouts occur when UCCX does not receive presence available status from the agent PC/browser.  The system logs the agent out after 60 seconds.

So, seen all this points, there are 2 more difficult things to be caught, and I recently came across.

  1. Browser.
    Chrome v88+ and Edge are known to cause these issues.

    For agents logged out with the tab minimized/backgrounded:Disable Automatic Tab Discarding:
    For versions 75 and above: Add chrome extension ‘Disable automatic tab discarding’https://chrome.google.com/webstore/detail/disable-automatic-tab-dis/dnhngfnfolbmhgealdpolmhimnoliiok
  2. IntensiveWakeUpThrottlingEnabled Starting with Chrome 88: Improved resource consumption for background tabs To save on CPU load and prolong battery life, Chrome will limit the power consumption of background tabs. Specifically, Chrome will allow the timers in the background tabs to only run once per minute. If agents are using Chrome v88+, navigate to “chrome://flags” in the agent Chrome browser, search the above flag and ensure it is disabled (default=enabled).

  3. Network LatencyOne of the Finesse requirements is the that the Network Latency cannot be higher than 400ms.
    And that was exactly the problem I found on my network!!!

    But how do we find out that the latency is going over 400ms??

    Here are the instructions to gather the clientlogs from the agent Desktop side,

      *   Clear browser cache
      *   Load the following URL: <protocol>://<ip/host>:<port>/desktop/locallog and select “Sign In With Persistent Logging“.  You will be redirected to login page with the appropriate query parameter url.
      *   Sign into Finesse
      *   Operate Finesse as usual
      *   When you run into the problem open a new window or a tab and reopen with same browser type using the following URL: <protocol>://<ip/host>:<port>/desktop/locallog and select Refresh button
      *   Now you have all the logs in the contents of the console output.

  4. Conclusion


    After analysing the logs, I could find the following:

    Line 384: 2021-03-29T09:28:50.812 +02:00: 39DED1: <a href="http://<http://<<uccx_server>&gt;: Mar 29 2021 09:28:50.728 +0200: Header : Client: 2021-03-29T07:28:50.518Z, Server: 2021-03-29T07:28:50.434Z, Drift: -84ms, Network Latency (round trip): 587ms

    image

    In this Log’s pieces, we can see that the roundtrip latency for the agent that was logged out, spikes above the 400ms threshold allowed by Finesse. This latency means that the server does not receive the “Presence available” notifications from the agent PC.  After 60 seconds without receiving a notification, the system will log the agent out per design.              

  5. So now you have to troubleshoot your network to find the source of that Latency.

    That’s it guys!

    I hope this post can help you out!

    See ya!

    Bruno

    Creating an ODBC connection with UCCX

    Hey everybody,

    Today  I want to show you how to create an ODBC connection with UCCX, which can be mainly used for Wallboards/Dashboards.

    To be able to access and pull information out from its Database, UCCX already provides some users with some specifics rights. They are:

    • uccxwallboard: Has access to real-time database tables that contain snapshots of real-time statistics, more specifically to tables RTCSQsSummary and RTICDStatistics.
    • uccxhruser:  Has access to many configuration and historical tables in the UCCX database. It can only be used for custom historical reporting and Cisco Unified Workforce Management (WFM).
    • uccxworkforce: Has access to the Team, Resource, and Supervisor tables and it’s used for Cisco Unified Quality Management (QM).

    For this connection we are creating now, we are going to use uccxhruser.
    Let’s start off going to UCCX >> Tools >> Password Management to set a new password (in case you don’t know)

    image

    Once done, let’s now focus on the ODCB configuration!

    First of all, you need to download the IBM Informix Client SDK. It will allow the client to stablish a ODBC connection with your Database on UCCX.
    You can download the SDK here.

    • Go to Control Panel >> Administrative Tools >> ODBC Data Sources (64-bit).
    • Chose the tab System DNS and hit Add.

    image

    • You see now a list of available data sources. Select IBM INFORMIX ODBC DRIVER. Click Finish.
    • Time to create a new DNS. In the Tab General, give a name to your connection.

    • Go to the Tab Environment, and fill the information following the rules below:
      • Server Name: Instance name of Informix server of the set up.  Please pay attention because there are tricky rules for entering the name such as:
        1. Name MUST be in lower case (even if your server name are in upper case)
        2. Any hyphens MUST be converted to underscore
        3. If your server name begins with a number, add “i” in front of it.
        4. Add “_uccx” to the end of the hostname.

      For example: If your server name is 1-EMEA-UCCX, you have to enter i1_emea_uccx_uccx

      • Hostname: The actual hostname or IP address of the UCCX
      • Service: 1504
      • Protocol: onsoctcp
      • Options: leave it blank
      • Database name: db_cra
      • UserID: uccxhruser
      • Password: Password of uccxhruser

      image

      • Go now to the Tab Environment.

            Fields Client Locale and Database Locale must be as: en_US.UTF8

      3

      • Go back to the Tab Connection. It’s now time to test if it’s working.

      Click on Apply and Test Connection. You must see that message:

      6

      That’s it for now! I hope this post can be useful !!

      See ya!!