Tell me and I forget. Teach me and I remember. Involve me and I learn.
- Benjamin Franklin
I don’t have to tell you this, but we live in complicated and highly uncertain times. In the past several months we’ve had to confront a pandemic of epic proportions, a worldwide economic slowdown, and an awareness of the huge racial divide that exists in our country. On a personal note, I lost a job in May, started a new one in July, and saw (from a distance) my 93-year-old mother move from her home of 63 years into an assisted living facility. On their own, each event has been life changing. Taken as a whole, it’s amazing that I am still standing.
I say all this to explain why I haven’t written a blog article in many weeks. It’s not that there hasn’t been a lot on my mind. On the contrary, every day has held enough material for a book. Finding something to say isn’t the issue. It’s finding the time and energy to write it down.
But here I am again and although I am still busier than a cross-eyed rooster on an anthill, I feel compelled to write. I also feel that if I don’t write something today, it will be weeks before the next “free” moment comes around.
If you have been following me on LinkedIn, you’ve seen all the fun I’ve been having with Avaya Spaces APIs. I started small by working with the many REST web services it exposes. While those are very powerful and I was able to come up with some very clever applications, I’ve been working with REST for so long that I can write POSTs and GETs in my sleep.
What intrigued me was that Spaces supports a socket.io interface that accomplishes most of what the REST calls do and then some. And if you know me, it’s the “and then some” functionality that makes me happiest.
The easiest way to think about socket.io is to picture a subscribe and publish framework. In the case of Spaces, an application will subscribe to a Spaces channel (think Spaces room), listen to events that occur on that channel, and publish its own events that cause actions to take place. For example, an application might subscribe to a Help Desk room, receive notification of Help Desk chats and tasks, and send its own chats that members (human or software) of the Help Desk room see. Under the covers, WebSockets are used to transport information to and from Spaces and the application, but the gory details are hidden from developers. Instead, programmers work with simple objects, methods, and callbacks.
Avaya has done a good job documenting the Spaces Socket API, but if you are like me, you need to see the APIs inside a working application. Thus, the reason for this article.
The Spaces Socket API can get complicated fast, so I started with something easy – chat between a web page and a Spaces room. Now, I am no great web developer, so I did what I often do. I stole code from someone else and modified it. In the process, I learned enough to do it all by myself the next time around, but still feel the need to be honest about it.
The user interface is very simple and looks like this:
The three buttons do the following:
- Connect: Connect the application to a Spaces WebSocket and subscribe to a particular room.
- Socket Send: Send a text chat message to the Spaces room via a socket emit.
- API Send: Send a text chat message to the Spaces room via the Spaces REST API.
The application flow is simple. The user navigates to the chat webpage and clicks Connect. Once the socket connects and the subscribe is successful, text can be entered into the Message window. That text is sent to the room by clicking either Socket Send or API Send. The sent text is then shown in the big display window. Conversely, any chat message typed into the actual Spaces room is received and displayed by my web application.
In this example, I logged into Spaces on my iPhone using my gmail account (Andrew P.) and the application is logged into the Spaces API with my Avaya account (Andrew Prokop). I then sent chat messages from the webpage and Spaces application.
The Spaces room sees this:
The use cases for adding Spaces chat to a web page are plentiful. This functionality is useful anytime you want to connect to a Spaces room without launching the Spaces application.
First, the html:
Connecting to the WebSocket is accomplished as follows:
If you read the Spaces API document I linked above, you will see that there are two ways to authenticate with Spaces. The best way is via OAuth2. The easiest is to use a JSON Web Token. I used a JWT, but be aware that JWT tokens are static and expire without warning. Still, for demo purposes it’s an easy way to get an application up and running without a lot of effort.
To obtain a JWT, start Spaces on a Chrome browser. Click F12 and then click on the Application tab. Once there, open up Cookies and click on the Spaces cookie. Scroll down the right panel until you see AUTH_TOKEN. That really long string of characters is your JWT. Copy it and put it into the code as “token.”
The Guts of the Application
To subscribe to a Spaces room, you need the spacesID. You will find that in the URL for the space. It’s the hexadecimal number after “spaces/.” Copy it and put it in “spacesID.”
Next, you need the id of the user. This is a little more complicated, but not too hard. With something like Postman, execute the /users/me API call described here, and grab the “_id” value that’s returned. Put that number in “idUser.”
Note the two “on” callbacks. The first is invoked when the WebSocket connects. Within the callback, it emits a SUBSCRIBE_CHANNEL. This connects the application to the room you want to chat with.
Inside the SUBSCRIBE_CHANNEL callback, the application enables the Message text box and the two send message buttons.
Now that the application is connected to the WebSocket and Spaces room, it’s ready to send and receive chat messages. Chat messages are sent by emitting SEND_MESSAGE on the WebSocket. The body of the message is encapsulated in a JSON structure.
You can also send messages via the REST API like this:
Note: You do not need to connect to socket.io to use the REST API. They are completely independent of each other.
The last important aspect of the application is receiving notification when a new chat has been added to a Space. This requires a callback for the MESSAGE_SENT event. In my callback, I look to see this is a chat message (the callback will notify of things besides chat) and where it came from. I discovered that messages from a web browser Spaces room come in html format. Those generated on my iPhone or from an emit do not. I also clean up the encoding for single and double quotes.
Other than a few odds and ends, that’s pretty much it. I hope it all made sense and that you learned enough to create applications even better than what I’ve done.
I plan on tackling establishing a video call from a web page to a Spaces room next. There are still several unanswered questions that I need to figure out. Give me a time, though, and I’ll get there.
It’s my hope that you walk away with two things from this article. First, there are several ways to tackle Spaces from a programming point of view. You can use the REST APIs or the socket interface. Second, the socket interface allows you to create responsive applications that direct Spaces to do something while being dynamically informed when something is done. For me, that’s where the coolness starts.