A Knife in the Dark

I have happy memories associated with Little House on the Prairie and the other books by Laura Ingalls Wilder. Some people seem to consider the books to be “girly” or fluff, but I think them to be a great read both for what they are and for the memories experiencing the books with family.

I was about five or six when my mother read the series aloud to me and my older sister.  The things I remember most from the story are 1) the kids using the pig’s bladder as a ball and 2) the snow fort and subsequent snowball fight.  But what I remember best was that while my mother was reading about the struggles of the Ingalls’ family, my father would quietly appear in the doorway behind her and mime the story–somehow even the most somber of stories was hilarious when depicted in that manner.  When my sister and I would burst out laughing, my father would disappear behind the corner before my mother could turn around.

A few years ago, while visiting my parents, I stole those same books (which technically belong to my sister) to share with my children.  We spent a few months of after dinner reading time working our way through the series.  The kids found the stories interesting and entertaining.

In order to carry on the tradition of silliness, and also to make sure everyone was paying attention, I would occasionally slip in a little bit of extra content.  Typical favorites would be to add “A Ghost in” at the beginning of a chapter name and/or append “of Doom” to the end.  So while reading These Happy Golden Years and not long after advertising “Sleigh Bells of Doom”, I read out the chapter title “A Knife in the Dark”.  Nobody believed me until I displayed the actual text.  So now that chapter (or at least the title) is probably the family favorite and best remembered both for the ominous tone and for the memory of disbelief.

Some may say that the “Little House” books are for girls, but to me they represent fatherhood.  For the stories about about the fathers in the books.  For the stories acted out by my father.  And for being a father with children dubious about a chapter entitled “A Knife in the Dark”.

Watching the Eclipse

Apparently if I were to drive about 21 miles southwest from where I live, I could experience eclipse “totality”. Instead, I’m going to stay home and be satisfied with 99.3% coverage of the sun.

Like most people, the family procured eclipse glasses.  We also pointed the telescope at the sun and directed the view piece onto paper.  Viewing it on the paper made it easier to see the actual movement.

 

 

 

 

 

 

Another interesting thing we observed was that the sun shining through the trees created slivers of light shaped the same as the mostly obscured sun.

Back in 1984, when I was about the age of the girl child, I remember seeing an eclipse in Montgomery, Alabama.  I hope the kids have happy memories of today.

Dynamically downloading a JAR and adding to classpath

I recently had a situation where I had a JAR that had dependencies on another JAR, but wouldn’t always be packaged with the other JAR.  I’m not completely happy with what I ended up doing, but since I succeeded in doing what I wasn’t certain was possible, I decided to document it.  Basically (as the title suggests), I tweaked my code so that at runtime it will download the JAR and add it to the classpath.

Downloading from a URL

Normally I’d use something like the Apache Commons IO library to help with downloading the JAR, but since that’s one of the pieces in the JAR to be downloaded, I’m in a catch-22 situation.  Instead, I used vanilla Java for the implementation.  I ran into some minor complications because the server hosting the JAR did not have a signed certificate, so I had to force Java to ignore certificate errors.  Fortunately, no authentication was required–otherwise things would have been a bit more complicated.  Here is my class:


package com.nathanbak.gomi;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class UrlDownloader {

    /**
     * Downloads the specified URL to the specified file location. Maximum size
     * allowed is <code>Long.MAX_VALUE</code> bytes.
     *
     * @param url
     *            location to read
     * @param file
     *            location to write
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     * @throws IOException
     */

    public void download(URL url, File file) throws NoSuchAlgorithmException, KeyManagementException, IOException {
        TrustManager [] trustManagers = new TrustManager [] { new NvbTrustManager() };
        final SSLContext context = SSLContext.getInstance("SSL");
        context.init(null, trustManagers, null);
       
        // Set connections to use lenient TrustManager and HostnameVerifier
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new NvbHostnameVerifier());
       
        InputStream is = url.openStream();
        ReadableByteChannel rbc = Channels.newChannel(is);
        FileOutputStream fos = null;
       
        try {
            fos = new FileOutputStream(file);
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        } finally {
            if (fos != null) {
                fos.close();
            }
            is.close();
        }
    }

    /**
     * Simple <code>TrustManager</code> that allows unsigned certificates.
     */

    private static final class NvbTrustManager implements TrustManager, X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
   
    /**
     * Simple <code>HostnameVerifier</code> that allows any hostname and session.
     */

    private static final class NvbHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}

Adding JAR to classpath

This was my first foray into dynamically changing the classpath at runtime.  I found many examples of how to load a specific class (when you know the full class name) from a JAR file, but there wasn’t as much information about stuffing a JAR of whatever into the current, running classpath.  After much trial and error, this is what I finally produced:


package com.nathanbak.gomi;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;

public class JarAdder {
    public void addJarToClasspath(File jar) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, MalformedURLException {
        // Get the ClassLoader class
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        Class<?> clazz = cl.getClass();
       
        // Get the protected addURL method from the parent URLClassLoader class
        Method method = clazz.getSuperclass().getDeclaredMethod("addURL", new Class[] {URL.class});
       
        // Run projected addURL method to add JAR to classpath
        method.setAccessible(true);
        method.invoke(cl, new Object[] {jar.toURI().toURL()});
    }
}

The addJarToClasspath() method wasn’t necessary on my Windows system.  My main JAR had a classpath to the dependency JAR specified in the MANIFEST.MF and as long as the JAR was downloaded there, it would be found.  However, on Linux it didn’t work and so the method is necessary (and it doesn’t seem to hurt anything on Windows).

Other thoughts

  • It is important to do the download and classpath changes before calling any code that depends on the stuff in the JAR.  Even imports in the same class can cause problems.
  • The downloadUrl() method is pretty generic and could be reused in a lot of situations provided the content being downloaded doesn’t get to big.
  • Different versions of Java seem to behave differently–I’ve only tested two Java’s so far (one on Windows and one on Linux), but have seen very different behaviour.
  • Since the certificate checking is disabled and code is loaded and at runtime, it seems like it would be an easy setup to attack or hack.
  • This method could potentially be used for applications to self-update without needing to restart.

Conclusion

I’m not sure this is a permanent solution for my problem, but it does work for the time being.  Also, I think the parts I learned while going through the process have potential to be used in future situations.

Escaping to Discworld

A couple years ago I had a lovely six months reading through Robert Jordan’s The Wheel of Time series.  This summer I’m binging on Sir Terry Pratchett’s Discworld novels.  I’ve read most of them before, but I’m really enjoying consuming the books in mass quantities.  There are several reasons I think they make great summer reads.

It’s nice not to have to worry about what to read next–you just grab another book in the series.  However, the Discworld series adds an extra dimension because I can easily jump around between storylines thanks to Jakub Oleksów’s reading order guide (there are newer versions than the one in the link, but they don’t always seem to mention the artist and I think he should get credit for his creation).  If I should need a break (I didn’t) from the misadventures of Rincewind (a “Wizzard” who cannot do magic), I can easily switch to another storyline such as the city watch or industrialization.  So in the Discworld series there is something readily available for any mood (or at least any of my recent moods).

The Discworld novels, for the most part, are written such that they can be appreciated on various levels.  The entire family engaged in much laughter as we read aloud Tiffany Aching’s encounter with the Nac Mac Feegle in The Wee Free Men.  Boy #1 and Boy #3 can read through the same book and enjoy it for entirely different reasons with Boy #1 commenting that he “got” so many more of the jokes on his second read now that he’s older.  Boy #3 decided to build The Mended Drum out of Popsicle sticks.

It’s easy to pickup where you left off (or even where you’ve never been) in Discworld.  The novels are great to take with on vacation because it’s not necessary to reserve a few hours in a special reading spot in order to appreciate the text.  I just tossed a couple of books in the suitcase when packing for each trip in July, and had something to enjoy as time permitted.

Some people categorize Pratchett’s Discworld novels as silly (they are) or state that it’s not “real” fantasy (just another way of saying silly), but that is the intent.  I’ve heard some people say that if you’ve read one Discworld book, you’ve read them all, but that is like saying if you’ve eaten one ice cream cone, you don’t need to eat another one since each book provides its own unique satisfaction  So this summer, even though I’ve been keeping busy, when I do find a few minutes to escape, I love heading over to Discworld.

Unit testing Java main() methods

Most of the code I write does not go into Java main() methods and I’m quite accustomed to testing code in “normal” methods.  Recently, however, I came across a situation where I needed to confirm a defect, verify a fix, and perform additional testing of a handful of edge cases related to the functionality of a main() method.  In this post I describe the solution used.

First, some disclaimers to help define the scope and also recognize that I’m doing a couple things that I would normally best practices:

  • Since the main() method is usually the entry to the entire application, running it normally involves a lot of code.  In this case I want to only test the functionality of the code in the main() method itself and not the functionality of stuff that it calls–these are real unit tests.
  • There are already many unit tests in place using JUnit so I want to continue using JUnit and be able to run everything together.
  • Generally I think it’s poor form to to modify code to make it testable–code that is well-written should already be easy to test.  However, I occasionally make exceptions such as making a method protected instead of private in order to expose it to testing (I think that’s a lot cleaner than using reflection to run a private method).

So, here’s a very simplified example of the class with which I started (note that the non-main methods are not implemented):

package com.nathanbak.test.main;

public class Application {

    protected Application() { }

    public static void main(String[] args) {
        String string = args[0];
        Application application = new Application();
        try {
            application.run(string);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
        }
        System.exit(0);
    }
    
    protected void run(String string) throws Exception { }
    
    protected void logException() { }
}

I try to avoid putting much code in main() methods, but typically end up having things like:

  • Parsing/validating arguments (something the above example does poorly)
  • Object instantiation
  • Running of object methods (often with arguments)
  • Providing some sort of top level exception handling and user output
  • Provide a relevant exit code (typically 0 for success and 1 for failure)

When I tried creating JUnits for the main() method, here are some problems I encountered:

  1. If a test called the main() method, the test run would halt because of the System.exit() call.
  2. Verifying output to System.out is difficult.
  3. Running the main() method means running the run() method which can take a long time and changes the scope of the test.
  4. It’s hard to test edge cases (such as what if the run() method throws an exception that doesn’t have any message).

I was worried that #1 was going to be a deal breaker, but fortunately found an easy solution in System Rules which bills itself as “A collection of JUnit rules for testing code that uses java.lang.System.”  I added the system-rules-1.16.0.jar to my classpath, followed the examples on the main page, and had a great solution to #1 and #2 above (as well as solutions to various other problems I hadn’t considered but will keep in mind for the future).

To cover #3 and #4 above was where I had to get a bit more unorthodox.  I created a private static method that creates and returns the new object and replaced the constructor in the main() method with a call to that new method.  I also added a protected static property that I could use to store an instance and had my new static method use that instance if it was not null.  This is now my class turned out:

package com.nathanbak.test.main;

public class Application {

    protected Application() { }

    public static void main(String[] args) {
        String string = args[0];
        Application application = newApplication();
        try {
            application.run(string);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.exit(1);
        }
        System.exit(0);
    }
    
    protected void run(String string) throws Exception { }
    
    protected void logException() { }

    protected static Application instance = null;
    
    private static Application newApplication() {
        return instance == null ? new Application() : instance;
    }
}

With the ability to control the object used to run methods, I was able to create tests like:

package com.nathanbak.test.main;

import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;

public class ApplicationTest extends Application {

    @After
    public void tearDown() throws Exception {
        instance = null;
    }
    
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void testMain() {
        instance = new CrashAndBurn();
        String [] args = { "one", "two", "three" };
        exit.expectSystemExitWithStatus(1);
        main(args);
    }
    
    private static class CrashAndBurn extends Application {
        @Override
        protected void run(String string) throws Exception { 
            throw new Exception();
        }
    }
}

A few things to note about the test class:

  • The test class needs to extend the class under test in order to have access to the instance property.
  • The testMain() test currently calls main with some args and then the CrashAndBurn class throws an exception when the run() method is called and the test confirms that the main() method returns an exit code of 1 (the test would fail if any other exit code was returned).
  • The tearDown() method sets the instance back to null after every test to ensure that specific instances are only used when desired for specific tests.

Obviously my real tests are more numerous and comprehensive, but the above example shows how I was able to overcome the difficulties encountered when trying to create unit tests for a Java main() method.

Let there be light (again)

There was a broken light switch in the upstairs hall.  Since I knew I was going to go through the trouble of replacing the switch, I decided to get another fancy smart switch.  This time I went with the TP-Link Smart Wi-Fi Light Switch.

The TP-Link switch is a lot like the WeMo switch (see part 2).  In fact, it was an accident that I got that switch–I intended to get another WeMo, but wasn’t paying attention and bought the TP-Link instead.  It took awhile for me to notice that things were different.

The wiring of the switch was simple and pretty much identical to what I did for the WeMo.  I did notice that the switch packaging was different, and the switch was slightly different, but the differences are so minor that I initially assumed I had a slightly different model of the same thing.

It wasn’t until I started trying to connect the TP-Link switch to the Echo that I ran into problems.  Most of the problems stemmed from the fact that I was going through the same steps I did for the WeMo.  Once I realized that the switch was different, it wasn’t immediately obvious where to find instructions (there was nothing helpful in the box).  After searching online, I discovered that the setup is a bit more complicated and required installing the TP-Link Kasa app, creating a Kasa account, installing a special Alexa skill, and linking the accounts.

Now that everything is set up and working, there’s no different from the WeMo in terms of functionality.  The switch works like a switch and the lights can also be voice activated via Alexa.  The thing that I like least about the switch was that the setup was comparably more complicated, but some of that was due to incorrect assumptions on my part.

Configuring a Raspberry Pi from Another Computer

Introduction

One thing I like about the Raspberry Pi is that it’s a small gadget that, once configured, only needs power in order to sit somewhere and do something.  For example, BakBoard runs on a Raspberry Pi that only plugs into a TV (for both power and display).  Unfortunately, in order to get everything running, I typically have ended up connecting various extra wires (network, keyboard, mouse, display) and work directly on the Pi before I can stick it in some random location to do what I want it to do.  Below are the steps I figured out so that I can do everything from my main computer and the only wire I need to my Pi is for power.

Prereqs

  • My main computer is currently running Ubuntu 16.04 although I think it would be easy to adapt the steps for most operating systems.
  • I have an SD card (32 GB in my case, but it probably only needs to be about 4GB).
  • I have an SD card adapter so I can read/write the SD card from my computer.

OS Image

To get the base image, I went to the Raspberry Pi Downloads Page and grabbed the latest Raspbian image (specifically 2017-01-11-raspbian-jessie-lite).  Once I had downloaded the zip, I opened it and then doubled clicked the image file (2017-01-11-raspbian-jessie-lite.img).  This brought up the Ubuntu image tool and it was easy to “restore” the image to the SD Card.

Wireless Networking

Since I don’t want to mess with a network cable, I want my Pi to be able to access my wireless network.  In order to do so, I modified the interfaces file.  It is in the image at etc/network/images.  Basically I changed the bit:

iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

To be:

iface wlan0 inet dhcp
    wpa-ssid "NATHANS_NETWORK"
    wpa-psk "NATHANS_PASSWORD"

Obviously I plugged in the correct network name and password.

Enable SSH

The Raspbian OS used to have SSH enabled by default, but last year that changed as a security precaution.  The explanation for the change (and where I learned to do what is described below) is described on the Raspberry Pi Blog.

Basically, to enable ssh, I just create a file called “ssh” in the boot directory.  The contents of boot/ssh don’t matter–apparently the OS will see that file, enable ssh, and then delete the file.  The tricky part was that there were two “boot” directories.  There was one at the root of the volume, but there was actually a separate volume as well that is named boot–that’s the one where the ssh file must be created.

Authentication

The default password to  the Raspberry Pi is well-known which is nice because I don’t have to remember yet another password, but also a security risk since everyone knows it.  Instead, I like to use key based authentication and disable password authentication for ssh access.  Here’s how I did that:

First, I generated my public and private key (that was done a long time ago, and there are plenty of sources on the Internet how to do that).  My public key is id_rsa.pub (in the .ssh folder in my home directory) and the private key is id_rsa.  That creation was on my main computer.  Then, on the Raspberry Pi volume, I created the directory home/pi/.ssh.  I then copied the public key file (id_rsa.pub) into the home/pi/.ssh folder and also copied the file and named the copy “authorized_keys”.

Then, to disable password authentication via SSH I opened up the file etc/ssh/sshd_config in a text editor and changed:

#PasswordAuthentication yes

UsePAM yes

To be:

PasswordAuthentication no

UsePAM no

Conclusion

Once the above has been completed, I can stick the SD card into the Raspberry Pi and then plug in the Pi (giving it power).  It automatically connects to the wifi and I’m able to SSH into it without a password.  There’s nothing new here that can’t be found in various places online, but I’ve gathered the pieces together for my own reference at least.  Here are a few “gotchas” I encountered along the way:

  • All of the paths mentioned above are relative paths–the volume might be mounted in various places–in my place it was something like /media/nathan/90asd8f60s9g69789sd6gjherlkuyds8 for the main volume and /media/nathan/boot for the boot volume.
  • As mentioned before, there are two “boot” directories–make sure that the “ssh” file is created in the boot volume.
  • In order to create/modify some of the files, I had to use sudo (or change to root).
  • I the past, I used to have to run raspi-config to expand the volume to use all available space on the SD card, but that no longer seems necessary–it now seems to happen automagically.
  • Even though password authentication is disabled for SSH access, whenever logging in there is still a warning.  I usually do change the password and just write it down somewhere since I never use it.

And the question is?

I was still in elementary school when I was first introduced to The Hitchhiker’s Guide to the Galaxy.  Initial contact was the 1984 video game on a Commodore 64 which I initially thought to be a clone of Zork, but quickly discovered it was much sillier.  I died frequently and never made it very far, but I learned to put on a robe before trying to access the pockets and to lay down in front of bulldozers.

Later (but still during my elementary school years), the BBC showed the television series.  I was expecting something like Doctor Who (and Douglas Adams even wrote “City of Death” which is one of my favourite Doctor Episodes), but quickly discovered it was much sillier.  Of all the bits in the show, the thing I remember the most is at the Restaurant at the End of the Universe where the animal that wants to be eaten.

In middle school I finally read the first book and in high school school I read everything available in the series at the time.  I also explored and enjoyed the world of Dirk Gently and his Holistic Detective Agency (my favourite part of those books being the sofa in the stairway).  By then I was sufficiently well-versed in the works to be able to claim to know the location of my towel.

In college there was a guy in the dorm that had the original radio show in cassette tape and he was kind enough to let me make a copy.  I’m typically not a fan of that sort of audio format–it’s much slower than reading and requires more effort than media that has associated visual components.  Nevertheless, I really enjoy the radio show and it is my preferred version of the story.  Over the years first the radio show (now in mp3 format rather than cassette) has continued to provide entertainment during road trips.

I enjoy the silliness associated with “The Guide” in all it’s many forms–it has been and continues to be a source of entertainment for me and my family.  If I had to choose a favourite media format, I would have to go with the radio show version.  While I suspect that more people have read the book, I feel it is definitely worth a listen.

 

 

 

Let there be light (part 3)

In Let there be light (part 1) I played with Phillips Hue home automation and in Let there be light (part 2) I tried out the WeMo Light switch.  Both solutions work well where they are used in my home.  In this post, I’m going to compare the two and mention some things I like and dislike about the different approaches.

Cost

Retail for the Phillips Hue starter set (a hub and two bulbs) is about $70 and an Amazon Dot costs $50 so it would have cost $120 to do Boy #1’s room, but Amazon had a Black Friday deal and so I got everything for $90.

The WeMo switch is around $40, so that paired with a Dot would normally be $90, but I managed to save $20 on the Dot during a special promotion so my actual cost was $70.  Had I gone with Phillips Hue (even without needing to purchase another hub) I would have had to spend about $14 for each of six bulbs meaning it would have been $84 without the Dot.

The WeMo switch is a cheaper initial investment.  Also, assuming that switches last longer than bulbs, I think maintenance costs will also be lower.

Installation

The installation of the Phillips Hue doesn’t require messing with any wiring which is nice, but it does require setting up the hub.  The hub needs power so it has to be plugged into an outlet and it also requires a physical (wired) network connection.  Putting the bulbs in place is just like changing an ordinary light bulb.

The installation of the WeMo switch is just like swapping out any other light switch.  The switch does require having a neutral wire (not to be confused with a ground which is optional)–since my house has the neutral wire it isn’t an issue, but some homes are wired differently.

If you already have a hub in place, it’s definitely easier to screw in a new light bulb than to install a new switch.  It is also safer and requires less skill.  However, having a hub does mean one more device in the home that requires power and a physical (corded) network connection.  I think Phillips could have done better and put everything into the bulbs and not require the hub at all.

Other Aspects

  • Manual switch: With the Phillips Hue bulbs, the existing light switch can function normally, but if you use it to dim the light, that becomes the new 100% for the bulbs.  Also, if you turn it off, than the bulbs are unable to work at all via voice control.  The WeMo switch works as one one expect and doesn’t have any conflicts with voice control.
  • Dimming:  The Phillips bulbs allows dimming, but the WeMo switch is only on or off.

Conclusion

Overall, I like the WeMo switch better than the Phillips Hue bulbs.  However, there are two reasons why I’m not adding many more switches to my home.  The first is that the switches do not support multiple switches controlling the same circuit (ie they cannot work as three way switches)–compared to all the functionality already crammed into the switch, it seems to be as though it wouldn’t be overly complex to add support for that.  Also, the switches do not have dimmer functionality.

Let there be light (part 2)

My bedroom has two light switches and both of them are in awkward locations.  Because of the double door entry, access to one switch requires maneuvering around and behind one of the doors and it’s actually easier to walk across the room and use the switch in the middle of the far wall which is not near anything.  This does mean that the room must be traversed in darkness when entering or exiting.  A similar ill illuminated jaunt is required between the switch and the bed at night.

For years I have joked about getting a Clapper for the light.  However, when I tried to persue that I learned that they don’t seem to make Clapper hard wired light switches, only outlet devices for lamps and other things that use a plug.  Seeing the convenience allowed to Boy #1 with his voice activated lights, I decided to enact something similar.  Since the master bedroom has a ceiling fan with six separate bulbs, I didn’t want to go with a Hue like we did for Boy #1 in Let there be light (part 1).  Instead I decided to try the WeMo Light Switch.

It took awhile to get the switch installed, but it wasn’t particularly difficult.  Most of the time was spent running back and forth to the circuit breaker and testing wires to figure out which was which–part of the complication was that I was replacing a 3-way switch with a regular switch.  Also, the wire colors weren’t what one would normally expect.  Once the switch was in, it worked like a switch should–I could use it to turn the lights on and off.

After the switch was installed, I then had to configure it to work with Alexa.  It was similar to what I did for the Hue, so it went quickly.  Again I was happy that I didn’t have to create a new account or do anything too quickly.  I was expecting more difficulties, so I was pleased that things went smoothly

Anyway, as I approach my dark bedroom I can now turn on the light with a voice command.  And when I’m nestled in my bed, done reading for the night, and ready to sleep, I can just bark out some words and have the light go out without the necessity for a mad dash.