Saturday, April 2, 2016

Sheraton, Bedbugs and how NOT to do Customer Support

Adventures in Bed Bugs
I've traveled enough to know that bed bugs are always a risk at any hotel stay. Generally, I do a pretty reasonable check of the room on arrival. When I find them, I insist on being put up in another hotel. Finding bed bugs is usually difficult. They hide well and the best approach is to look for fecal matter (little black/brown spots -- blood of past guests -- on the bedding and box springs).
Usually, I won't leave bad feedback on one of the travel sites, tweet, or otherwise publicly shame a hotel. Very few things are more damaging because people have no idea how common of a problem it actually is (if they knew, they might just stay home and skip traveling all together). And usually the property handles the situation well.  This time is different. I've never had a hotel and hotel chain so completely disregard such a serious problem.
Sheraton Lake Beuna Vista Hotel, Orlando, Florida
We failed to notice the problem until our very last day, and considering how bad it was I can only plead laziness on my part. When my wife and I arrived and saw the room adorned with bright white sheets, bedding and even comforter, we were lulled into a false sense of security. We stayed there 4 days and on the final day, my wife shot out of bed after she scratched at her leg and found the small sting had a source -- a bed bug.

It was about 8:00 AM and I had been looking forward to sleeping in a little bit after a hard week of work at a conference. That idea was instantly shattered. My wife grabbed one of the Zip Lock bags we put our toothbrushes in and captured the bugger. We brought it down to the front desk and returned to the room to get some more photos. It didn't take but a few seconds to find the second bug hanging around the head board.

Up came the mattresses. What we discovered was nauseating.

Those "fecal matter" inspections, had I bothered to do them, would have immediately had me leaving the room. On top of fecal matter, we found four bugs that were smashed under both beds' box springs. My assumption is that the infestation had been present in the room when things were being moved around and nobody in housekeeping had noticed. Considering the large, smashed, blood stains and pieces of dead bug that were very easy to see, I'm terribly disappointed that staff paid so little attention, though after my experience dealing with Starwood in general, I can't say I'm surprised. Housekeeping should be trained to identify fecal matter and other secondary evidence of the presence of bed bugs and should never have allowed a guest to occupy a room suspected of having an infestation. Had the hotel been paying any reasonable amount of attention, though (or had I), they would have seen the critters actually walking around.
Working with the hotel
The hotel staff kept our luggage and gave me a new bag to place that I could use to bring the three computers I had traveled with home. They assured me the items would be returned to me via FedEx with the clothes heat treated. They explained that the other items could not be heat treated but did not explain what would be done with them. We had to fly out that morning so I couldn't stick around long to ensure things were handled correctly so we trusted the hotel. In retrospect, I should have been less trusting.
Lesson 1: FedEx doesn't mean fast, anymore
Years ago when someone said "we'll Fedex that to you", it meant overnight. The delivery business has changed a lot--a fact I know well--but that didn't stop my mental picture of receiving my belongings in a reasonable amount of time from kicking in. I mean, obviously, these are my things and I expected to go home with them the night I returned so I assumed the hotel would understand the urgency of returning my belongings quickly. I don't travel enough to warrant buying "two of everything". The hotel sent our luggage back FedEx ground, which took a week. All of my wife's makeup was in the bag as was my shaving products. We had to buy replacements.
Lesson 2: Expect others to treat your stuff with little respect
I kind of expected my suit coat was going to need a pressing after its week-long journey. But I didn't expect my belongings to be destroyed.  Because they placed my wife's makeup, a pen, and the rest of our toiletries in an unsealed bag, we found a mix of interesting stains on many of our clothes.  My suit coat has a large black ink stain and pinkish-brownish sain from hairspray-mixed-with-pen-and-makeup.  Most of the rest of the clothes suffered similar fate.  Worse, being in an unsealed bag and not knowing what was done with those items, I didn't know if they were safe to bring in my home, so the luggage went from the porch to the shed (where it remains today).  I'm out about $500 in destroyed clothes (this doesn't include the original bill for the stay)
Customer Service in an Age Without Humans
It's been about 4 years since I've had to work with a hotel to get something like this resolved. My past experience was with a different chain, so it's possible this is related only to Sheraton, but my sense in dealing with other Customer Service related things is that customer service has suffered greatly in the age of text. My first instinct was to send a message via e-mail. Visiting Sheraton's Web site yields a contact form -- nothing I can attach photographic evidence that truly explains the severity of the situation to. I started there and replied to the auto-reply with 8 photos I had snapped (we took a video also). Both cases yielded an e-mail reply with a reference number (different for the sent and replied). Both assured that I would be contacted. Neither were ever replied to, so after two days I made my first call. I referenced the e-mail and was given a reference number and was told that the team who deals with this sort of problem is being engaged and I'd hear back from them soon. I also received an e-mail stating that I'd receive a reply "in five days" (not business days but I had figured this might be the case). Nine days later, I called back hoping this would get me to someone who could directly address the problem.
I started off the call explaining my situation (which left the CSR speechless for a moment) and asked for a manager. I was passed off to "the manager" and explained what had happened. After a bit of hold time to review the problem (given a reference number I had to hunt down), I was told that it was being handled by Consumer Affairs. Ok, so can hand me off to whomever is handling it at Consumer Affairs? No. They gave me an e-mail to reply to. I explained that I'd now had six different messages ignored by them via e-mail (one directly to the hotel I stayed at) and that I would really like to talk to someone who's job it is to actually solve the problem (I was far more polite than my writing makes it sound like). I asked to speak to her supervisor.
Supervisors In Name Only
It's long been a game in the CSR world that "Manager" and "Supervisor" really means nothing anymore. Most people get frustrated enough to ask for Supervisors and CSRs are already at a disadvantage having to field more calls than they have people to field them. If every call has to be passed to a Supervisor then they have to have a lot of supervisors. This last supervisor was the least helpful, explaining again that there is absolutely nothing she can do and the only option I have is to e-mail the magic, general, e-mail box for Consumer Affairs. No, thanks.
Finally, I took to twitter, posting 5 of the photos I had taken and @ing Starwood. I received a reply from SPGassist claiming I'd "gotten their attention" and to DM them my reference number. They failed to follow me, though, so I couldn't. I replied with my reference number immediately after they sent the tweet and asked them to follow so I could DM. I sent my phone number to their twitter account expecting, as had happened with other situations where I'd involved Social Media, to get a call that day. It's been 24 hours and *crickets*.
Contrast with Another Property
I'd experienced this at another property four years ago. This time I discovered the problem when I arrived. I went to the front desk and asked for them to put me up somewhere else. Without even an argument, my request was granted. They, too, took my bags and sanitized them, returning them to me that evening as well as providing me with a new toothbrush and razor. The guy who delivered my luggage hung around while I went through everything to make sure it was all there and done to my satisfaction. They gave me 4 times the points for my stay. When I arrived home, the hotel manager at the first hotel called me to not only check in that everything was in order, but to assure me that they have completely stripped/sanitized the room I stayed in so that future guests would not have the problem I had. To this day they are among the two brands I am loyal to. Look, bad things can happen when you travel and Bed Bugs are one of the common "worst" things that can happen. But when it's handled well it's not going to keep me away -- if anything, I now know that "Another Property" brand not only takes the problem seriously, but should that problem happen to me again I know it'll be addressed in a professional, prompt manner. What I've learned from this experience from Starwood is that even in a serious manner such as Bed Bugs, I can expect to have to chase Customer Service around for a month and ultimately have to write, in vein, about it which tells me there's little-to-no hope should something less serious happen to me. No thanks.  I'll be sending a few more e-mails elsewhere and one snail mail, certified letter, but I'm done with chasing general mailboxes and the non-existant people behind them.

Saturday, March 19, 2016

Fix: Serial TTY Terminal Output on Raspberry Pi 3 is Garbled, Garbage or Otherwise Broken

You've prepped your Raspbian SD card. You've plugged in your FTDI / RS232 adapter to your shiny new Raspberry Pi 3, set up Putty for 115200, Parity 8, Flow Control None, Stop. You've wired everything correctly, Ground to Ground, Tx to Rx, Rx to Tx, and you plug-in, only to be greeted by garbage. Lots of garbage. Blocks, Corners, non-English characters. It looks like your modem looked when it blew off a BBS connection in 1992. But it was just dandy with your Raspberry Pi 2! What gives?
What's happening
Bear with me since some of this may be inaccurate. I'll be honest, the last time I dealt with troubleshooting a serial terminal connection was easily 18 years ago. This shouldn't have happened, really. In my teen years, I actually coded a FOSSIL COM driver into Bulletin Board System software I had written for my multi-node BBS (get off my lawn!). 18 years and many lines of code later, I'm feeling senile.
So with serial communication, there's always the sensitive issue of timing. Your Pi is trying to send data at 115200bps. It's failing. Somewhere along the mystical way, the CPU clock rate is set in such a way that it doesn't quite deliver at the right speed and the result is the text vomit you're seeing in PuTTY.
The Fix
The fix is simple, but has side-effects. If you're simply setting up the serial terminal in order to login and configure WiFi because you're too lazy to walk 10 feet to another room and plug in an Ethernet cable, it's a perfect solution. If you are interested in using serial communication for some other purpose, it's not.
Simply plug the SD card into your PC. Open up the "config.txt" in the root in something that will understand the line endings properly (Notepad++, Atom, Visual Studio Code, Sublime, ... basically anything other than Notepad). Insert the line "core_freq=250". Save and safely eject the card. Pop it back into your Raspberry Pi 3 with everything plugged in and you should see the majestic, properly formatted, vomit-free boot sequence. Login and you're good!
Once you're done and network connected, remove that line from the config.txt (located in /boot/config.txt if you're editing directly on your RPi) and reboot. You'll be back to the original, faster clock speed (and broken serial communication).

Friday, March 18, 2016

HowTo: Add yourself as a local administrator via DirectAccess only connected PC

You've just been offline domain joined to your domain and you login with your account only to discover that you're a non-administrator on your laptop! This won't do, so you hop launch Computer Management using a local administrator account or Microsoft Account that's an administrator and try to add your Active Directory ID. You soon discover that though Computer Management thinks it can see the domain, it can't seem to find the account that you're actually logged into the computer with!
Why It Doesn't Work
Honestly, I'm not sure on this one. My hypothesis is that Computer Management launched as a local admin is not able to use the DA tunnel, but it knows you're in a domain and expects that it can get to it. This is backed up by the long (Not Responding) message as you wait for it to fail. Bummer.
The Fix
Use a tool that is so old that it can't possibly fail! Kidding. But it is old. Remember the "net" command?
Launch a Command Prompt (cmd.exe) as a local administrator (or Microsoft Account with Local Administrator access).
Type in:
net localgroup administrators YOURDOMAIN\youraccount /ADD

I believe you're going to have to use your SamAccountName (old style DOMAIN\account) rather than UPN (, but the latter may work. I didn't try it so I simply don't know. :)

Thursday, February 18, 2016

Monitoring Local Presence Changes in Lync Client SDK


I’m giving a talk remotely today to the DFW Unified Communications Users Group on Skype for Business development and will be showing some of the code related to my simple Raspberry Pi LED Status tool.  The code behind the project was thrown together in under an hour and really isn’t a great example of best practices, however, it’s a good place to get an idea about how to do some basic development with the Skype for Business Client.

In this post, I’ll go through some of the code used for that project.  This post is based on the initial commit, so make sure you’re referencing that in case I’ve got the bug and decided to update it.

The Lync Client SDK

Yes, Lync.  Unfortunately, it wasn’t updated for the Skype for Business release, however, it works fine with the latest client.  You’ll need to be running the latest Lync 2013 client or Skype for Business client in order to use solutions developed with Lync Client SDK, however, you require no other components to actually run the program—it’s all included with the client.


Download the Lync Client SDK (search, I won’t provide a link due to Link Rot regularly wiping them out) and install it.

You’ll need to reference Microsoft.Lync.Model.dll and Microsoft.Lync.Utilities.dll.  They’ll be located in the Office15 folder…somewhere.

A Note about Multi-threaded Code

The Lync Client SDK provides a set of APIs for interacting with the client using multi-threaded code.  This means that you’re going to have to be cautious with certain operations.  Many things you’ll want to work with are fired on events in a background thread and all of the perils of multi-threaded programming will apply.  You’ll see a few things I’ve done to combat this, but the code in the initial commit is by no means fully audited to ensure thread-safety and a lot can go wrong in this area!

Interacting With the Lync Client

In the constructor for the Monitor class, you’ll see everything you need in order to connect to and interact with the Lync client.

// Connect to the current Lync Client
m_client = LyncClient.GetClient();
var contact = m_client.Self.Contact;
if (contact == null) // There's better ways to do this, but this works in a dirty implementation
 SimpleLogger.Log("Client is not logged in - Setting Offline", m_gpioController.AllOff());
 throw new InvalidOperationException("Client must be logged in before starting the monitor");
// Create a subscription and subscribe to our own contact object
contact.ContactInformationChanged += ContactOnContactInformationChanged;
var contactSubscription = m_client.ContactManager.CreateSubscription();

The connection occurs at LyncClient.GetClient().  This method will throw if the client is not launched.  I chose not to catch that exception since it effectively renders the application dead.

From there, I subscribe to the ContactInformationChanged event and add a subscription to my local contact (m_client.Self.Contact).  This ensures that when any property of my contact changes, the method “ContactOnContactInformationChanged” will fire (on a background thread).

When Contact Information Changes

I have a pretty simple event handler defined for that:

private void ContactOnContactInformationChanged(object sender, ContactInformationChangedEventArgs e)
            if (e.ChangedContactInformation.Contains(ContactInformationType.Availability))
The "e" property lets us know what specific modification caused the event to fire. It's common for more than one thing to change at a time, but since I only care about the Availability component, I check for it and fire off "SetLedState". The changed information is not included, just the component that changed, so we have to look that up. This is done via the following in SetLedState();
var contact = m_client.Self.Contact;
if (contact == null)
object availabilityId = contact.GetContactInformation(ContactInformationType.Availability);
var availability = (ContactAvailability) availabilityId;                
In this application, I'm only subscribing to the local contact's presence so I simply grab that contact's Contact object. Availability is an int boxed in an object, not a ContactAvailability enum as one might expect, however it's simple to just cast that to ContactAvailability for easier decoding. From there, I "switch" on the ContactAvailability and set the LEDs using the GpioController class.
What’s up With All The Interlocked Stuff in GpioController

Remember all of that multi-threaded nonsense I mentioned earlier?  I implemented Blinking using a Timer, which is a class that lets you fire off a method on a background thread at a given interval.  Because of this, and because our status changes come on an event handler that fires on a background thread, there’s a few members of our GpioController that could be modified by more than one thread.

Normally I’d use a lock, and that would be fine here, as well, but the requirements for this application were simply to ensure that the variable being read is the latest copy in memory.  Lighter weight patterns work fine in this scenario and I use them enough that I simply go there when the kind of variable fits well.

In addition, the GpioController is disposable because that timer needs to be cleaned up.  The Dispose pattern that’s commonly used is not thread-safe.  I’ve included a class in the Patterns class that handles it in a thread-safe manner.  There’s not going to be a case in the application, as it’s currently written, where the GpioController will be disposed on anything but the main UI thread, however, I anticipate that future changes will introduce this and I’d rather not fix that later.  For the most part, you can ignore that class.  If you’ve not done a lot with the Interlocked static methods, you’ll find it to be confusing.

The GpioController keeps a “current LED state” in a flags enum.  Enums are effectively syntactical sugar over ints with constant fields.  I developed a NuGet package that contains a number of helpers for flags enums and includes a wrapper to provide “safe” access to an enum from multiple threads, providing guarantees that when the “Value” member is set, any getters on another thread will always receive the latest value instead of what happens to be in the cache for the core your code is executing on.

The only other place that needed protection was around the blinking feature.  To protect that, I used an int variable in place of a bool and Interlocked to ensure it’s updated and read properly.  Let’s look at that more closely:

// Check that the light is actually blinking and set it to NOT blinking in a threadsafe manner
if (Interlocked.CompareExchange(ref m_isBlinking, 0, 1) == 1)
 m_timer.Change(Timeout.Infinite, -1);
 Thread.Sleep(m_currentBlinkInterval.Milliseconds * 2);

The Interlocked bit serves two purposes. First, it ensures that the value of m_isBlinking is both read and written to in a manner that guarantees the latest value will be retrieved. It also ensures that if two threads hit this code at nearly exactly the same time, only one will execute the statements in the if block, modifying our timer and incurring the penalty from sleep.

What the code is actually doing is saying "read what is actually stored in m_isBlinking" and if it's set to "1", set it to "0". Then, check the value that was previously stored in m_isBlinking and continue into the body of the "if" only if the previous value of m_isBlinking was "1".


The code is pretty thoroughly commented, so I’d encourage you to look at each of the methods in each of the classes for more information.  You’ll see I’ve put an event handler in for detecting power events, which is a good idea when your application is going to run on a laptop/tablet.  It’ll catch the “Suspend” event and let you do anything you need to do to clean up before suspending.  Beware that this code should be simple, since the machine can hit suspend before your code is finished executing.  I use it to turn the LEDs off and catch the Resume to ensure the application doesn’t crash when coming back up (the Lync Client API will fire events before you can actually get at the data contained within the Contact class, but it’s easy to detect and prevent while resuming).

Making a Network Connected Raspberry Pi Display Your Presence State on LEDs


I work from home full time and at Modality, we use Skype for Business for all of our conference calls and other communications needs.

Being a work from home employee with children, particularly one who doesn’t like to lock himself in his office, I wanted a way to let my family know when I cannot be interrupted.  And being a geek with geek kids, what better way to solve the problem than with legos and a Raspberry Pi?

Items Required

A Raspberry Pi – I used a Model B (non-Plus).  Any Raspberry Pi model should work provided you can get it on the network somehow.  These cost about USD $35.00.  This would likely work with a Banana Pro, as well (about $45.00) and using that would give you wireless out-of-the-box.

A Network Connection – I purchased a RealTek WiFi+Bluetooth Adapter.  Personally, I wouldn’t recommend this product since it required compiling a driver since the kernel didn’t have native support for it.  Refer to the compatibility list for the least effort in getting WiFi working.  If you’re using the Banana Pro, you won’t need to worry about this.

3 LEDs – Green, Yellow, Red if you want to keep with the colors that Skype for Business uses.

3 270-330 ohm resistors – one for each LED.

Wires and a Breadboard – or some other way to connect them to the GPIO pins.

Legos to build an ugly case (optional).

An SD card that works with the platform you’re using (I recommend sticking with 16GB to give you space to play around).

Setting up the Software

I won’t go into the full setup instructions for a Raspberry Pi, but you’ll want to get it up and running.  I used the DietPi operating system, but this will work with Raspbian and I’d recommend using the NOOBS tool to install if you’ve not done an RPi install before.

You’ll need WebIOPi in order to interact with the GPIO via the web.  This came preinstalled with DietPi.

Update the Raspberry Pi OS

I did the installation with the latest bits as of the writing of this post and it’s always a good idea to be up-to-date.  You’ll want to either connect via Secure Shell (PuTTY works well for this on Windows) or plug your RPi into a display and keyboard to get a shell.  Once you’ve gotten a shell up, run these commands (and grab yourself a cup of coffee).

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rpi-update
Configure WebIOPi

The GPIO pins aren’t configured the way we need them to be, yet, so we’ll edit the WebIOPi configuration to get that going.

$ sudo nano /etc/webiopi/config

Nano is a simple console text editor.  Locate the heading labeled [GPIO] (hint: CTRL+W can be used to find text in Nano, however, GPIO should be at the top).  Anything with a “#” in front of it is ignored (a comment). The configuration under GPIO is “PIN = DIRECTION STATE”.  If you have 17, 18 and 27 already setup in some way, you’ll want to modify those lines.  If they are not configured at all, you can simply add the following lines.

17 = OUT 0
18 = OUT 0
27 = OUT 0

Locate the [HTTP] heading and make sure it is setup as follows

# HTTP Server configuration
enabled = true
port = 8000

# File containing sha256(base64("user:password"))
# Use webiopi-passwd command to generate it
passwd-file = /etc/webiopi/passwd

# Change login prompt message
prompt = "WebIOPi"

Locate the [REST] heading and make sure it is setup as follows

# By default, REST API allows to GET/POST on all GPIOs
# Use gpio-export to limit GPIO available through REST API
gpio-export = 17, 18, 27

# Uncomment to forbid changing GPIO values
#gpio-post-value = false

# Uncomment to forbid changing GPIO functions
#gpio-post-function = false

# Uncomment to disable automatic device mapping
#device-mapping = false

The rest should be fine as is.  Hit CTRL+X and choose “Yes” to save the file.  Finally, we’ll setup a user/password that will let us authenticate.

sudo webiopi-passwd
Set up an ID and password of your choosing.
Wiring it up

The wiring for the project is pretty simple.  Here’s a diagram that explains how to set everything up.  Make sure your resistors are wired correctly! I’m not an EE guy, but in my reading the warnings indicated that failing to install resistors or using the wrong resistors will result in damaging the Raspberry Pi.

It’s also important to note that LEDs are one-way devices.  If you install them backward you won’t break anything, but they won’t light up (which is the first thing to check if your tests don’t work).


That’s the GPIO arrangement of a B (non plus version).

That’s it, you’re ready for the code.

On Your Windows Box

The code is client-side, so it won’t work if your PC is turned off or asleep, but it’s the easiest way to do it and doesn’t require administrator privileges on the Skype for Business server as would be if we’d done this with the Unified Communications Managed API (though it can be done with a bit more work that way).

You can get the source code from the GitHub Repo.  I’ll provide a compiled version, but because the software is very hastily designed, you’ll need to build it yourself.  You can download Visual Studio 2015 Community Edition to compile the project.

Running the Application

Hit Win+R and type CMD.  Go to the folder that the application compiled to (usually ProjectName\bin\Debug) and run:


If you’ve configured it following this gude, you’ll put “8000” for the port.  When started in “Test” mode, it’ll blink all of the LEDs and cycle through each one so that you can verify your wiring.  Fix any wiring issues and when you’re all set, run it with the same command above but without the “test”.