It’s so hard to know how to decorate a space. What color should the walls be? What sort of furniture works best for these room dimensions? Where is the best place to hang this picture of Jean Claude Van Damme holding a puppy?
I don’t know the answer to any of those questions — except maybe the third (“above the bed”) — but I did solve some of my own decorating dilemmas by letting the internet set the color of my office via an internet-connected lightbulb.
Setting the mood with LIFX
I have a simple LIFX mini-color lightbulb. I should mention that you can buy one yourself and save 20% on with the code IENJOYLAMP thanks to the folks over at LIFX. I don’t make any money off of that if you do, but it makes LIFX like me more, and isn’t making sure everyone likes you the real point of life?
I have made dozens of projects with my LIFX bulb. It’s one of my most favorite things. I put together a site called “www.ienjoylamp.com” (because ilovelamp.com was already taken) with a UI that just set the color of my lamp.
ienjoylamp.com not only allows you to change the color of the bulb; which you can do right now by the way.
The live stream is powered by Nest and it is SIGNIFICANTLY delayed. If anyone has a better idea on a simple Live Stream’ing setup that won’t be so damn slow, please, for the love of all that’s holy, let me know.
So I built this — primarily out of a strong sense of boredom and too much boxed red wine — and I tweeted it out…….and nobody cared.
Then about a month or so later, I tweeted it out again…
That tweet was picked up and RT’d by Jeff Sandquist, and the entirety of the internet descended on my lightbulb. Which teaches us that if you really want someone to do something, make it about the children.
This has continued ever since. I’m not kidding. Even as I write this post my lightbulb is changing every few seconds and it is over a month later.
Every time that bulb changes color, I know that someone, somewhere did that and for this brief moment, no matter where in the world that person is, we have a connection. Each color change is like tiny micro-interactions with people all day long even though we never spoke any words at all.
Wait — did I just discover the cure for introversion?!
What’s kinda interesting about this project is that it is using Vue, a NodeJS API AND web sockets. There is more going on than meets the eye.
Azure Functions API
The primary endpoint that the front end calls is not very complicated at all. It has one method “setColor”.
That’s essentially the entire API. It’s a thin wrapper around LIFX’s own API. It’s just proxying request through to LIFX’s servers, but abstracting that into an API of our own gives some nice benefits…
- I can obscure my LIFX token because it’s hidden behind my API.
- I can control who can call this API with the CORS settings in Azure Functions.
- I can use Azure Functions tokens for security and rotate them at will.
- I can add in realtime with the Azure SignalR binding.
Going real-time with Serverless
Shortly after my lamp made the rounds on Twitter, Anthony Chu tweeted at me and said…
Now the first commandment of open source says, “Whosever requests a feature, so shall they also present a pull request as a pleasing sacrifice”.
And shortly thereafter, said sacrifice was presented AND pleasing…
When you change the color of the lamp on ienjoylamp.com, it changes the background color of the site to match. Anthony did is wired up the site so that your background will change whenever anyone anywhere changes the color of the lamp. That means that we’re all now connected in some small way.
It’s all so emotional.
Anthony did this by tying in my existing API to Azure SignalR.
SignalR originated as an ASP.NET abstraction on web sockets. It reduces the boilerplate and wiring that you have to do as a developer, as well as dealing with things that you would rather just not, like falling back to long polling if a client doesn’t support web sockets. Although it’s 2019 and pretttttty much every browser supports sockets.
Azure SignalR abstracts this a bit further and turns the whole thing into a hosted service that you send and receive messages from.
You can set it up from the Azure Portal like any other Azure service.
The service then gets created and sits out there in the cloud like Mary Poppins.
In order to talk to this thing from Azure Functions, we have to create a binding for SignalR. To do that, you have to install the Azure SignalR binding for Azure Functions.
func extensions install --package Microsoft.Azure.WebJobs.Extensions.SignalRService -Version 1.0.0-preview1-10025
Now you need the connection string for the Azure SignalR instance that was created. That can be found in the “Key’s section of your Azure SignalR service in the portal.
Add that connection string as a variable in your
Then add a binding in the
function.json file for the SignalR service we created earlier.
With that binding in place, we can send a message to the Azure SignalR Hub. This block of code from the earlier snippet in this article does just that.
The “target” is the name of the name of the method that you want the Azure SignalR hub to evoke. Any clients that you want to be notified about this event will need to listen to the
colorChanged event, which we’ll get to in just a second.
Before we can actually connect a client, we need to add a place for the client to connect. By convention, SignalR looks for a “negotiate” endpoint. This will make more sense in a second, but for now, we need a second function in our API called “negotiate”. All this endpoint does is return the hub connection information, along with a token that allows the client to communicate with the SignalR service.
This new function is an HTTP Function, and it is just called “negotiate”. Add in a binding for Azure SignalR in the
Note that Anthony named the “hub” after me. You can name your hub whatever you like. Just be sure that you use the same name in all your bindings so you are talking to the same hub.
Now brace yourself for the code…
All that’s doing is returning the connection info for the SignalR hub.
My apologies up front for there not being enough boring information there. Would you like me to pontificate about the virtues of async/await? No? You would rather get a root canal? Moving on then.
We’re now ready to wire up a frontend to all of this.
Wiring up the lamp
The frontend of this application is built with Vue, because that is the new hotness AND there is already an awesome color picker component available for Vue called vue-color. It’s so easy to use it makes your teeth hurt.
Pretty nifty — yeah? Now whenever someone changes the color, I call the Serverless API and send the color value over. I also set the background color of the page at the same time.
NOW. Let’s talk about how we change the color of the page whenever someone somewhere else gets busy with the color picker.
For that we need to listen to the SignalR hub for changes and then update the page color. For that, we need the SignalR package from npm.
npm i @aspnet/signalr
Now we connect to the hub. Since I’m using Vue, I can do that in the component
Remember that this “colorChanged” callback will be called anytime we change the color on the server. Our Serverless API triggers this automatically when it changes the lightbulb color. So all we gotta do now is call the endpoint which sets the bulb color.
That’s pretty much the whole app right there. There are some latency issues to deal with in the actual app. For instance, when you change the color, you have to wait for the server to respond that the color was changed, and that is not immediate. What I do is show a spinner and then change the color of the page whenever the server responds that the bulb is updated — not before. That’s how you know FO SHO that bulb has been changed to the color on the page.
By the way, did you know that you can add an easy spinner to your app with Spin.js? It’s 2019 and what in life CAN’T be done with an npm package? God bless the internet.
Other stuff you can do
There’s lots of other stuff you can do with SignalR and Azure Functions. Real-time opens up entirely new realms of possibility. I’ve got a bunch of ideas on other things to do with this lamp site.
While I work on that, make sure you check out these Azure Functions / SignalR resources to get you started.
A quickstart for using Azure SignalR Service and Azure Functions to create a chat room.docs.microsoft.com