Are your co-workers pointing at their ear with a death stare when you approach their cube and then completely ignore you? Are you in the middle of a meeting and your wife is calling you over and over wanting to talk about the color of the baby's feces? How do people you interact with face to face on a daily basis know that you're available to shoot the sh--?

How about we leverage our Microsoft Skype for Business presence and let EVERYONE know EVERYWHERE what we are up to... and learn something while doing it.

I can talk to you, yes.

Skype for Business Presence Selection

Microsoft Skype for Business (formerly Microsoft Lync) "provides the infrastructure for enterprise instant messaging, presence, VoIP, ad hoc and structured conferences".

Hardware

We have chosen the WeMos components for this project. WeMos is one of the more compact designs, has the more recent ESP8266-12F SoC, and is stackable. The downside is they are shipped from Asia with a ~30 day shipping lead time. See you in a month and make sure you order more than one.

Solder the headers included with each shield as shown in the picture below.

Solder a jumper wire between pin D2 and D4 on the LED shield. This modification is necessary because the WS2812 library "uses UART1 routed on GPIO2 (Pin D4 on NodeMCU DEVKIT) to generate the bitstream". We assume that WeMos' reason behind this is to provide maximum stacking flexibility. Another side-effect of using pin D4 is that this pin also controls the ESP8266 on-board LED.

Snap the shields together.

To disperse the light we ripped off the lens from one of our PIR motion sensors.

Assembly

We covered the on-board LED with electrical tape to prevent blue light from bleeding through.

Print the attached STL files for the enclosure and press fit all the components.

You are done.

Software

WARNING: cleartext domain credentials are stored on the ESP8266! You can Indian gift this device to your enemy or compromise yourself.

The source is available within the 'skype' folder here.

We have chosen the NodeMCU firmware for this project. At the time of publishing the firmware is at version 1.5.4.1. If you are new to the firmware (or ESP8266) we strongly recommend the book 'Building an IoT Node for less than 15 $: NodeMCU & ESP8266'.

Required Modules

bit,cjson,file,gpio,http,net,node,tmr,uart,wifi,ws2812

1. Connecting to WiFi: Edit the wifi.secret file.

{ "ssid" : "your-network-name", "pass" : "your-network-pass" }

(yes, you have just saved your cleartext WiFi credentials to the SoC)

2. Connecting to Skype for Business: Edit the skypelt2.secret file.

{ "discover" : "https://lyncdiscover.your-domain.com", "username" : "user@your-domain.com", "password" : "your-enterprise-pass" }

(yes, you have just saved your cleartext domain credentials to the SoC)

3. Compiling Lua Source

After dumping the files into flash, we like to run the following snippet which compiles the Lua source, yielding a 10% savings on the heap.

node.compile('skypelt2-presence.lua') file.remove('skypelt2-presence.lua') node.compile('skypelt2-application.lua') file.remove('skypelt2-application.lua') node.compile('skypelt2-auth.lua') file.remove('skypelt2-auth.lua') node.compile('skypelt2-discover.lua') file.remove('skypelt2-discover.lua') node.compile('skypelt2-ramboot.lua') file.remove('skypelt2-ramboot.lua') node.compile('skypelt2.lua') file.remove('skypelt2.lua') node.compile('internet.lua') file.remove('internet.lua') node.compile('light.lua') file.remove('light.lua')

Lessons Learned

WS2812 OPERATION

We were curious how these LEDs worked. After reading the spec we hooked one up to a scope. It was very cool to see the bitstream!

CONSECUTIVE HTTP REQUESTS

You can not invoke an HTTP request from the callback of another HTTP request. The second (inner request) must be placed in queue.

This does not work:

http.get(uri,header,function(...) print('outer request callback') http.get(uri,header,function(...) print('inner request callback') end) end)

This does:

http.get(uri,header,function(...) print('outer request callback') node.task.post(2,function(priority) http.get(uri,header,function(...) print('inner request callback') end) end) end)

HTTP RESPONSE HEADERS NOT AVAILABLE

They are not passed back to Lua. We had to hardcode the UCWA Skype ticket issuer relative path in skypelt2-auth.lua.

OUT OF MEMORY CRASHES

Ahhh, this is always the fun part. The first iteration of our script was a single file which used up a lot of heap. The device would crash primarily after creating an application with UCWA. We figured out that the combination of the large HTTP response body and conversion from JSON to a Lua table could not be done alongside all other logic. We split up the script into individual modules and introduced a device restart. Modules are only loaded when needed and unloaded after their execution to free up the heap.

An even more drastic measure is to dump functions to flash and 'execute' on-demand from flash.

WiFi CREDENTIALS NOT SECURE

WiFi credentials are obtainable by dumping a specific address of the NodeMCU firmware.

LACKING OAUTH REFRESH MECHANISM

Unfortunately, the Skype UCWA OAuth flow lacks the ability to refresh an expired token. You are required to provide your domain username and password every eight hours when your token expires. You compromise your domain if the ESP8266 gets into the wrong hands.

Colors

Colors are defined in light.lua.

local COLORS = { RED = string.char(0,255,0), GREEN = string.char(255,0,0), BLUE = string.char(0,0,255), YELLOW = string.char(255,255,0), PURPLE = string.char(0,128,128), MAGENTA = string.char(0,255,255), WHITE = string.char(255,255,255), BLACK = string.char(0,0,0) }

Flashing WHITE means the device is configuring itself. This includes Skype web link discovery, authentication, and application creation. Flashing PURPLE means that the device has lost WiFi connection or the Skype secret file has been wiped from the flash. BLUE means that the Skype server returned a presence enumeration that is not understood by the device. Flashing of any other color defined to display your presence means that the last presence request has failed. In this case we flash your last known presence as it might not be accurate. The color selection for your presence is defined in the skypelt2.lua file.

if _availability == "Away" then light:set(light.COLORS.YELLOW) elseif _availability == "BeRightBack" then light:set(light.COLORS.YELLOW) elseif _availability == "Busy" then light:set(light.COLORS.RED) elseif _availability == "DoNotDisturb" then light:set(light.COLORS.RED) elseif _availability == "IdleBusy" then light:set(light.COLORS.RED) elseif _availability == "IdleOnline" then light:set(light.COLORS.GREEN) elseif _availability == "Offline" then light:set(light.COLORS.GREEN) elseif _availability == "Online" then light:set(light.COLORS.GREEN) else light:set(light.COLORS.BLUE) end

What's Next?

Use the ESP32 SoC with 10x heap

The release of ESP32 promises ~400KB of heap and lots of other functionality. This does not mean that you can write lax code. Continue to push the SoC to its limits and draw your own conclusions. For example, by running out of heap on the ESP8266, it really made us question the server side requirements.

Offload the OAuth flow or implement supervised boot

It was great to find out how far we can push the ESP8266. In a production environment we would prefer to inject an MQTT based middleware that could perform UCWA operations on our behalf. However, we want to try something cooler in our next version. How about if we add an RFID reader to the device and store our domain credentials on a JAKCOM R3 ring? We can boot the device Gandalf style!