Learning Simple Self Service App Creation for UCCX with Philips HUE

Overview

One of the things Cloverhound specializes in is Self-Service IVR and customized apps for the call center. I also have a fond place in my heart for IoT and so I thought I would make a training blog on self-service IVR creation based around the Philips Hue.

We will make a small UCCX script that allows you to call in and enter the color code you would like to change the color of your lights too.

This will require us to bust out the java and write an integration with the Hue which is hosted here in github: https://github.com/chadstachowicz/PhilipsHueJava/blob/master/PhilipsHue.java

You can see a video of the final integration here: https://www.youtube.com/watch?v=NuBDHvkWAZo

Getting Started – The Hue

The Philips Hue product is really cool I love the range of colors they can do. Also, the white is extremely normal meaning I don’t notice a difference from normal bulbs. I personally love some of the deep blue and purples that they can do, these are my favorite to work to late at night, listening to some tunes. My current favorite song I listened to while writing this can be found here. https://www.youtube.com/watch?v=dQw4w9WgXcQ

So what do we need to know about the hue to make some cool stuff happen? The first thing we need to know is it uses a REST API hosted on what’s called the Hue Bridge. This is the device that plugs into your network with an Ethernet cord which controls your light bulbs. To the best of my knowledge the light bulbs are probably using the Zigbee protocol, which is a fast, short range wireless chips set. You can buy a starter kit of the bridge and 3 bulbs for $200 bucks. I admit it’s an expensive cool toy I couldn’t live without. Also, I am pretty sure the REST / Web interface running on the device is Rails.

One thing to note is that unlike the Nest API, there is no controlling your HUE from the cloud yet (without a custom adapter). The research I looked into said they were adding it and were expecting it by the end of the year. So one thing that is crucial for this setup, your Hue Bridge and UCCX must be on the same LAN, and have IP Connectivity.

The Hue – Talking with your bridge

The great news is that the HUE developer site is pretty good, and the HUE itself is super simple. One of the easier API’s to just pick up. It works with a traditional JSON put to a REST address. I am not going to recreate the wheel, all of the information to create a username (API Token) on your local bridge is here.

http://www.developers.meethue.com/documentation/getting-started

The API we are going to use to change the state of the light is as follows.

http://<bridge ip address>/api/1028d66426293e821ecfd9ef1a0731df/lights/1/state
  • use your API Key generated by the HUE Bridge.

We will need to send a ‘HTTP PUT’ with a JSON payload in the following format. A PUT is like a POST and generally used as a safer mechanism to update existing resources in a REST interface.   A JSON example is shown below.

{"on":true, "sat":255, "bri":75,"hue":47000,"alert":"none"}

Using this API combined with this payload we are asking for the light to do the following

  • Turn on light with ID number 1 (as identified in the URL)
  • Set it to a saturation of 255 (this is the highest setting, and really affects the deepness of the color/hue)
  • Set it to a brightness of 75 (this is the not that bright, and really just give a nice color output)
  • Use the color code 47000 (This is a number between 1 and 65535). There is a calculator located here, but this will produce a nice blue color I really like.

Hue Java Integration for UCCX

The next thing we are going to do is write a small Java interface to help us work with the HUE. The code for the project can be found here: https://github.com/chadstachowicz/PhilipsHueJava/blob/master/PhilipsHue.java

This is the code for a single Java Class named ‘PhilipsHue’. This is seen on line 11:

public class PhilipsHue

If your writing code for the first time ever, all we need to do is open a notepad or text editor to a file named PhilpsHue.java (Important note, your file needs to be named exactly the same as your class if you have any hope of getting it to compile).

The next thing we are going to do is define our imports. These are essentially the libraries or methods we want to use in our class. Libraries are modules to help you code faster by using code someone else has written and graciously donated to the community

These are going to be different every project you do, many of these are built in and distributed with the Java Runtime Environment, however we are using a third-party lib for JSON parsing. The first 7 imports shown below are needed in order to execute a rest request. I have written a re-useable function for this anyone is free to borrow to easily make further classes / REST integrations. The org.json.* will be used to parse our request and you will need to download the JAR from my dropbox or the Google. https://dl.dropboxusercontent.com/u/56846391/org.json.jar

The last import is for an Iterator method I use to loop later in the code.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.json.*;
import java.util.Iterator;

The next section is the class definition and the main function. One important thing to note, is if I just run the class directly from java, it will run the main function. Cisco UCCX however DOES NOT WORK with the main function, and you muse call an explicit method in your class. That is why all you will see in the following code is me passing the arguments straight through to a function named changeAllLights.

public class PhilipsHue {

  public static void main(String args[]){
    changeAllLights(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
  }
}

From here we are going to create 3 functions.

  • restRequest: This function is a generic wrapper to allow someone to call any type of HTTP method with any JSON payload. Feel free to borrow it. Both the other functions will call this function to perform the actual interaction with the Philips Hue Bridge.
  • changeLight: This will allow us to change the properties on a single light bulb. It will send a HTTP PUT request to
    http://<bridge ip address>/api/1028d66426293e821ecfd9ef1a0731df/lights/1/state

    with a JSON in the format of

    {"on":true, "sat":255, "bri":75,"hue":47000,"alert":"none"}
  • changeAllLights: This is the main function we will call from UCCX and is the most complex. If the third parameter, the ID parameter, is a number, we will assume this is the ID of the light bulb we are trying to change, and send a single PUT request to this ID. However if the ID is set to ‘All’, this will do a HTTP GET request to http://<bridge ip address>/api/1028d66426293e821ecfd9ef1a0731df/lights to get a list of all the lights that are controlled by the bridge. It will then parse out this list and send an individual changeLight to each ID that was returned from the first request, thereby changing all the lights on the bridge at once.

The restRequest function

I want to explain the rest request function a bit deeper since it can be the key to all kinds of integrations.

public static String restRequest(String surl, String type, String payload){
    try {

    URL url = new URL(surl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod(type);
    conn.setRequestProperty("Accept", "application/json");
    if (type.equals("PUT")){
      conn.setDoOutput(true);
      conn.setRequestProperty("Content-Type", "application/json");
      OutputStreamWriter osw = new OutputStreamWriter(conn.getOutputStream());
          osw.write(payload);
          osw.flush();
          osw.close();
    }

    if (conn.getResponseCode() != 200) {
      throw new RuntimeException("Failed : HTTP error code : "
          + conn.getResponseCode());
    }

    BufferedReader br = new BufferedReader(new InputStreamReader(
      (conn.getInputStream())));

    String output;
    String jsonData = "";
    System.out.println("Output from Server .... \n");
    while ((output = br.readLine()) != null) {
          jsonData += output + "\n";
    }
    System.out.println(jsonData);
    conn.disconnect();
    return jsonData;

    } catch (MalformedURLException e) {

    e.printStackTrace();

    } catch (IOException e) {

    e.printStackTrace();

  }
  return "Failed";
  }

This function takes in 3 params, the URL, the HTTP Request Type and the payload (if there is none set it to “”). From here we will make a connections to the URL, it is really important that we set the HTTP Header property of “Accept” and “Content-Type” to the correct settings if we want the server to understand we are sending JSON. If you do not to do this, JSON REST API’s will hate you and likely not work.

From here we send the request and will get back JSON data. The way that works is it comes in as a stream, so we are constantly reading it in and adding it into a String variable so we can parse it later. At the end if the function was successful it will return the captured data (generally another JSON with results or information we requested). In my code the changeAllLights is doing the JSON processing when needed.

Last thing to note is that we use a

try { } catch () {}

in order to do exception handling. Java will just error out and die if you don’t catch exceptions and process them.   You will see we just return the word “Failed” and a stacktrace if we fail.

The changeLight function

This is the simplest of all the functions. We basically use the parameters that are taken in to generate the parameters needed for the rest request. I am just creating string and passing them on with a ‘PUT’.

  public static void changeLight(String ip, String key, String id, String on, String sat, String bri, String hue, String alert) {

      String urls = "http://" + ip + "/api/" + key + "/lights/" + id + "/state";
      String json = "{\"on\": " + on + ", \"sat\": " + sat + ", \"bri\": " + bri + ", \"hue\": " +  hue + ", \"alert\": \"" + alert + "\"}";
      String retJson = restRequest(urls,"PUT",json);
  }

Compiling and Running the Java

The easiest method for this would be to put your org.json.jar file and your PhilipsHue.java in the same folder. Also ensure that JDK 1.7 update 46 or greater is installed on your machine.

From there we execute the following command to compile the source code file into a .class file, with the correct classpath to the org.json library.

Chads-iMac:Philips-Hue-Java cstachowicz$ javac -cp org.json.jar PhilipsHue.java

Next we package it as a JAR for use with UCCX.

Chads-iMac:Philips-Hue-Java cstachowicz$ jar cf PhilipsHue.jar PhilipsHue.class

Lastly we test this bad-boy before integrating to UCCX. We also need to point to our Library here in order to run it as well. Note how I separate my jars with a color instead of a semi—colon. This is a MAC OSX thing. If you are running windows, use a semi-colon.

The following made my lights blink a pretty blue for 30 seconds (This is what the alert settings of ‘lselect’ does).

Chads-iMac:Philips-Hue-Java cstachowicz$ java -cp "org.json.jar:PhilipsHue.jar" PhilipsHue 192.168.1.7 ad32e8a371850172530f6f64a8ab33 All true 255 75 47000 lselect

Output from Server ....

{"1":{"state": {"on":true,"bri":254,"hue":14910,"sat":144,"effect":"none","xy":[0.4596,0.4105],"ct":369,"alert":"lselect","colormode":"ct","reachable":true}, "type": "Extended color light", "name": "Home Office - Back Left", "modelid": "LCT002", "manufacturername": "Philips","uniqueid":"00:17:88:01:00:ea:40:3b-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"2":{"state": {"on":true,"bri":254,"hue":14910,"sat":144,"effect":"none","xy":[0.4596,0.4105],"ct":369,"alert":"lselect","colormode":"ct","reachable":true}, "type": "Extended color light", "name": "Home Office - Front Right", "modelid": "LCT002", "manufacturername": "Philips","uniqueid":"00:17:88:01:00:d0:dc:57-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"3":{"state": {"on":true,"bri":254,"hue":14910,"sat":144,"effect":"none","xy":[0.4596,0.4105],"ct":369,"alert":"lselect","colormode":"ct","reachable":true}, "type": "Extended color light", "name": "Home Office - Front Left", "modelid": "LCT002", "manufacturername": "Philips","uniqueid":"00:17:88:01:00:d4:8b:ff-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"4":{"state": {"on":true,"bri":254,"hue":14910,"sat":144,"effect":"none","xy":[0.4596,0.4105],"ct":369,"alert":"lselect","colormode":"ct","reachable":true}, "type": "Extended color light", "name": "Home Office - Back Right", "modelid": "LCT002", "manufacturername": "Philips","uniqueid":"00:17:88:01:00:d9:4c:52-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }}}

3

Output from Server ....


[{"success":{"/lights/3/state/on":true}},{"success":{"/lights/3/state/hue":47000}},{"success":{"/lights/3/state/sat":254}},{"success":{"/lights/3/state/bri":75}},{"success":{"/lights/3/state/alert":"lselect"}}]


2

Output from Server ....

[{"success":{"/lights/2/state/on":true}},{"success":{"/lights/2/state/hue":47000}},{"success":{"/lights/2/state/sat":254}},{"success":{"/lights/2/state/bri":75}},{"success":{"/lights/2/state/alert":"lselect"}}]


1

Output from Server ....


[{"success":{"/lights/1/state/on":true}},{"success":{"/lights/1/state/hue":47000}},{"success":{"/lights/1/state/sat":254}},{"success":{"/lights/1/state/bri":75}},{"success":{"/lights/1/state/alert":"lselect"}}]


4

Output from Server ....

[{"success":{"/lights/4/state/on":true}},{"success":{"/lights/4/state/hue":47000}},{"success":{"/lights/4/state/sat":254}},{"success":{"/lights/4/state/bri":75}},{"success":{"/lights/4/state/alert":"lselect"}}]

Uploading your code to UCCX

First thing we will do is log in to the UCCX and navigate to the System -> Custom File Configuration Menu.

Screen Shot 2015-08-09 at 11.49.07 PM

From here there is a quick link to the Upload Jar Files. You will want to upload both the org.json.jar and our PhilipsHue.jar.

Screen Shot 2015-08-09 at 11.52.18 PM

Now we will go back to the Custom File Configuration Page and move them over from Available Classpath Entries to Selected Classpath Entries.

Screen Shot 2015-08-09 at 11.51.25 PM

Please note that you MUST restart the CCX Engine and CCX Administration services for these classes to be useable.

Screen Shot 2015-08-09 at 11.55.53 PM

Creating a script to allows us to change the lights from our phone

Our script for this will be super simple. One thing to note, you MUST LOG IN to the UCCX server through the editor, if you log on anonymously it will not pull down the custom class. You must do this after uploading the class and restarting the CCX engine. Also, you must be able to resolve the UCCX server by FQDN to get this to work in the newer versions.

First we will create uccx script parameters as strings for all 8 of our parameters. They take the following as stated in the github readme.

  • param 1 = IP Address of HUE Bridge
  • param 2 = API Key for HUE Bridge
  • param 3 = id of the light (1,2,3,4)… you can also use “All” to do all lights on the bridge
  • param 4 = true/false for on/off of the light
  • param 5 = 0-255 for the saturation level (255 highest)
  • param 6 = 0-255 for the brightness level (255 highest)
  • param 7 = 0-65535 for the color
  • param 8 = “none, select (1 sec flash) or lselect (30 sec flash)” for the alert setting

You can name these whatever you want. My script file is posted here so you can take a look at exactly what I did. You probably need to upload the classes to your UCCX before this will open, due to the custom class reference. https://www.dropbox.com/s/7b54i9cbck4hczr/PhilipsHue.aef?dl=0

Next, we drag in a few elements, like the Accept contact step, to start the call. The get digits step, to collect our 5 digits from the caller, and our custom class call in order to change the lights. Last we will play a prompt to say it was successful, and then hangup the call.

My whole script including parameters is shown below.

Screen Shot 2015-08-10 at 12.10.01 AM

Here is a close up of our custom Java class in use. The easiest way to use a custom class is to use the Set method. This requires that your custom class actually return some piece of information (not void). In our case we are returning an integer from changeAllLights. If you don’t want to return anything, you can use the ‘Do’ step in UCCX.

Screen Shot 2015-08-10 at 12.10.35 AM

Here is the text version of what we used in the script editor.

PhilipsHue.changeAllLights( HueIpAddress , HueAPIKey , HueLightId , HueLightState , HueSatCode , HueBrightnessCode , HueColorCode , HueAlert )

From here we save the script and upload it to UCCX under the ‘Applications -> Script Management Menu’

The last step will be to make an Application filling in all of the info we need to make this guy jive. Here is what my application in UCCX looks like. This is configured under Applications -> Applications Management.

Screen Shot 2015-08-10 at 12.14.38 AM

As we can see we have set the following information.

  • IP Address of bridge is 192.168.1.7
  • API Key
  • All lights should be affected by the change
  • They should be turned on (state = true)
  • Default color code is 47000
  • Saturation of 255
  • Brightness of 75
  • No alerting mode (try lselect for some blinking J )

The last step is to create the trigger, as you can see I used 6010.

Conclusion

This was a really fun project. It would be really cool to find a good use case to use these HUEs in and we are playing with a few we have come up with. I also find this particularly cool for a lab because people can actually see what it is you did. That little bit of physical integration of the room makes a difference in customers believing you have the capabilities.

After a little playing you will notice the 65000 is reds, 52000 is purples , 47000 is blues and so on for the color codes. We actually find ourselves using this IVR to change the lights at work, but we are also ultra-nerds.

I hope this was helpful at learning some self-service IVR techniques. Send me a tweet or an email at cstachowicz@cloverhound if you have anything fun to add.

Here is a video of the final product. https://www.youtube.com/watch?v=NuBDHvkWAZo

Chad