Tuesday, July 18, 2017

Weekend Project: Reverse Engineering a Smart WiFi Dimmer Switch

Background


My wife Kayla and I like to spend our free evenings watching movies & shows, and after dealing with terrible cheaply made universal remotes for years, I finally caved and spent the money on a (refurbished) Logitech Harmony Elite remote/hub to control all of our media devices.

One of the great things about the whole Harmony ecosystem is that it supports a large number of home automation devices like thermostats, dimmer switches, etc… I’ve been interested in home automation stuff for a while, particularly since my cousin Nick showed a few of the things he installed in his house, but we rent a modestly sized two bedroom townhouse and don’t really have a good reason to spend the money and effort on a bunch of sensors, switches, and a potentially expensive hub.

That said, having a scriptable remote that can “talk” to a lot of devices made me want to play with something (...something useful, hopefully!). We decided to get a smart dimmer switch to control our living room lights, the idea being that it would be nice to be able to dim or raise the lights without getting up off the couch.

My criteria were:

  • Cheap (< $70)
  • Didn’t depend on a hub or other devices.
  • Worked with the Logitech remote.

That left me with essentially one option: a Leviton Decora Smart Wi-Fi Dimmer Switch (DW6HD-1BZ), available on Amazon at the time of this writing for $45.
The Amazon order arrived basically the following day. After doing some circuit breaker disco and making a quick walk to our neighborhood hardware store for some wire, the switch was installed and working!

Alas, that 3rd point in the list above ended up being an issue… Logitech’s compatibility page alleged that Leviton Decora devices were supported, but it neglected to mention that only IR ones were - I was out of luck with my wi-fi one. :(

Masochism


I can be stubborn when it comes to problem solving. In this case, it really rubbed me the wrong way that I had researched, bought, and successfully installed the dimmer, but couldn’t use the remote on it, which was the whole purpose of buying a smart dimmer switch in the first place.

A less masochistic person would have probably returned it and moved on with a stress free life. I, on the other hand, decided to jump directly into packet capture, decompiling, and API hacking.

Investigation


There were two different issues I had to solve:

  • Switch API. Given that the dimmer was controlled through wi-fi, it had to use some sort of protocol. I needed to understand and then be able to use that protocol.
  • Logitech Harmony API. Assuming that I could control the dimmer, I needed to somehow make the remote be able to interface with it.

I decided to tackle the second point first, since if there was no way to interface with the remote, reverse engineering was pointless. After some preliminary research, it seemed like the way to go would be to create a software wrapper over the dimmer switch that the remote would recognize as some other type of dimmer. That way I wouldn’t have to reverse engineer both sides, only the dimmer.

From what I read, other people have run into the difficulty of creating custom interfaces with the Logitech Harmony ecosystem, and the best thing to simulate seemed to be the Phillips Hue lighting system/bridge, particularly because there were already open source projects that modeled or used their protocol(s).

At first, I envisioned creating my own emulated Hue server Docker container or VM that would talk to the dimmer switch (having no shortage of always-on hardware in the house); but then found that the open source community had given me a much better starting point, namely Home Assistant, an open source home automation platform.

Home Assistant (HA) already had an emulated Hue bridge, as well as a very straightforward way to develop new device platforms. I wasn’t super familiar with Python, but that wasn’t a serious blocker given how similar Python is to Ruby.

I forked and deployed HA locally on my MacBook, configured the emulated Hue bridge, and successfully linked up with the fake bridge using the Harmony remote. So far so good!

The entirety of my HA emulated Hue bridge configuration:

About as simple as it gets.




In this screenshot below, the fake Hue is showing up in my Harmony Elite configuration. The remote found it automatically.


Reverse Engineering


Now we get to the hard part - figuring out how the dimmer switch sends & receives data.
This dimmer switch is designed to be controlled using Leviton’s My Leviton free app, which allows you to configure the wi-fi network it uses, group switches into rooms, rename them, control power and brightness, etc…
The way to go about anything like this is to start simple and obvious, and dig deeper only when necessary - so the first thing I did was just port scan the dimmer switch IP using Mac OS’s very handy Network Utility app (buried under /System/Library/CoreServices/Applications/ in newer versions of Mac OS).

As you can see, this produced a surprising result - the dimmer switch had no open ports!
OK, that’s weird. How does it communicate then? Encouragingly secure, I guess! ;-) Let’s go deeper and do a packet capture. Since I obviously can’t trace the packets on the dimmer itself, the My Leviton app traffic is what I want. Thankfully, Android has a great app called Packet Capture that can even dig into secure SSL/TLS packets (man-in-the-middle attack) if configured with a security certificate.

I turned on packet capture, hooked up an SSL certificate, and tried to log in to the My Leviton app. Unfortunately, it didn’t let me! Oops! That’s because Leviton actually verifies the certificate you’re trying to log in with… bad for breaking in, but a really good thing as far as a security measure. (Good job Leviton!)

OK, but we can still figure out in rough terms how the app communicates with the dimmer even if we can’t see the SSL traffic. Let’s just pass the encrypted packets through and see what we get. After recording and copying over the capture, we crack open Wireshark and get this (top snipped from a larger list):

Ordering by protocol, the only HTTP communication is to 192.168.0.19 which is the harmony hub (Note: the IP addresses for the hub and dimmer swapped due to some router DHCP manipulation I was doing, sorry for the confusion). The rest of the capture, about ~400 packets, is: TCP, TLS, and WebSocket packets to various addresses, NONE of which are the dimmer switch (now 192.168.0.22).
So, the port scanner was telling the truth! During normal operation, the app does not communicate directly with the dimmer switch.

There’s a second clue, implicitly revealed by an advertised feature of the My Leviton app - that you can control the lights in your house when you’re not home. This means that the app doesn’t have to be on the same network as the dimmer to be able to control it. So, here’s how this must work:
There are positives and negatives to this. On one hand, given that the communications have to go through WAN, there's a higher chance that the protocol is fairly high level - HTTP(s) and/or WebSockets, as opposed to some sort of proprietary binary format. On the other hand, there's a much worse likelihood of increased security to stop hackers from taking over unsuspecting homeowners' devices.

Now I had two options. I could either fiddle with security certificates and pursue attempting to break into the protocol through packet capturing the app, or I could go after the code. Packet capture dissection is no fun at the best of times, so I decided to try breaking into the code. The first task was to get the app itself onto my PC.

Android apps are packaged as APKs, which are compressed Java Archives along with any assets the app needs. On phones/tablets themselves, if you don't have root access, there's no good way of getting the APK off because they tend to be located in inaccessible system directories. However, there are a ton of websites that provide the ability to download the APKs directly off the Google Play Store. I won't link to the one I used due to their probable violation of Google's TOS. They're easy to find though.

Next, I used the open source Dex-to-Java tool JADX to decompile the app.

Cool! I was happily surprised to find that the Java code wasn't obfuscated at all, but unhappily surprised to find that there wasn't much Java to read and none of it had anything to do with device communication.

The mystery was quickly solved by looking up Cordova - a 3rd party library that appeared frequently in the codebase. Apache Cordova is a mobile development framework that provides multi-platform support for apps. It does this by delegating UI code to a WebView (essentially client-side HTML/CSS/JS) and providing integration tools to use native platform components. That means that out of the entire contents of the uncompressed APK, there were only two files of interest in the above screenshot: app.js and lib.js. Everything else was framework stuff, assets, or glue code.

Both of the Javascript files looked something like this when opened in a text editor:

Not very appetizing... That said, already some interesting stuff in here, like the words "CONNECTIONS", "CONTROLS", and "EDIT_RESIDENCES". Let's run this stuff through a js beautifier and make it easier to read.

That's much better. Lots of promising stuff here - clearly some API hosts and some "magic" IDs. The other file, lib.js had even more useful looking things like API endpoints and query formats.

Access & Control


Now that we can look through the app code, the first thing to try is logging into their service. Without authorization, we can't control anything. I like Ruby for quick prototyping, so after doing some "Find..." queries for "auth" in app.js and lib.js, I came up with this:

This gave me the following output:
Blurring the IDs just in case... ;-)

Fantastic. So I'm logged in and the service has given me an auth token. If I add that token to the headers for future requests, I'll be authorized to do everything the app does! Let's look up and use some other APIs in lib.js, particularly having to do with switches:

Those are some useful looking API endpoints! I eventually ended up with this Ruby script. Good code? Definitely not. But it works!

Running this script successfully turned on the dimmer switch in my living room and adjusted its brightness to 40%. Success!


Integration


Now that I've gained access & control of the dimmer switch, it was time to create a new Home Assistant component that would be linked to the emulated Hue bridge - finally accomplishing the original goal of controlling the dimmer with the Harmony remote.

I won't bore you with the details of me learning Python syntax on the fly, but suffice to say, the final code is very similar. There were a few things I improved from my Ruby prototype:
  • Using a session to communicate with the Leviton APIs. This reduced the request/response overhead and allowed me to just set everything up once.
  • Reconnection. The Leviton authorization codes are only valid for a limited time. Afterwards you have to re-authorize and get a new token.
  • Logging out when Home Assistant is stopped. Let's not leave any open sessions!
  • Usage of Leviton-provided attributes to determine valid dimmer brightness range.
  • Allowing Home Assistant automations to modify on/off transition time (because the APIs supported it)

You can see my final implementation in the pull request I submitted to the Home Assistant repository.

There are a few couple of things I left out either for another time or other implementers:
  • The Leviton APIs include sensors, thermostats, and many other controllable things. The right way to integrate this stuff with Home Assistant would be to write a more global device platform that can manage anything Leviton can access with their app.
  • It appears that the Leviton app can use a WebSocket connection as well as HTTP(s)... I didn't do much digging at this interface since the standard one worked. WebSockets can potentially be more efficient - and either way, having an alternative connection approach may be beneficial.

Finally, here's the dimmer as it looks on our Harmony remote:

Thanks for reading, I hope it was interesting!
-Tim

Wednesday, October 14, 2015

EuroTrip 2015

Overview

Sometime around two years ago, Kayla and I (along with Wyatt, Magnolia, Alex, Carrie, and a few others) started planning an epic European vacation, something long and going through multiple countries, centered around Oktoberfest in Munich. It took us a few months to do research, 4 months to put a rough plan together, then another 8 months to book all the different lodgings and coordinate our group. The trip went about as smoothly as any of us could have hoped for and the things we saw and did were amazing. :)

In the end, here are the overall stats:
  • Cost: $7000. We spent $4100 before the trip on travel/lodging bookings and the rest during the trip. We only went slightly over budget.
  • Duration: 14 full days in Europe, 16 if you count flying from/to the states.
  • Distance traveled: Approximately 2000km/1200mi within Europe.
  • Places visited: Prague, Plzen, Munich, Lindau, Zurich, Vienna, Kutna Hora. Also the airports in: Oslo, Dusseldorf, and Stockholm.
  • People joining us:
    • Wyatt & Magnolia were with us for most of the trip, with the exception of Zurich (they went to Budapest instead)
    • Alex & Carrie were in Munich with family and we only saw them on the 24th and 25th.
    • Tyler and the rest of his family were on the same flight in as us, and joined us in Prague and Munich, but then stayed in Germany and most of them flew back before we did.
  • Beer drunk: unknown but large amount. I estimate that we averaged about a liter a beer per person per day, which puts the trip total for Kayla and me at about 28 liters of beer.

So here’s our journey....

Red markers are the places we stayed, yellow are places we visited by train, green are the airports and flights.

Sunday, September 20th – 21st  - We fly to Europe!

  • Uber to Wyatt & Magnolia’s downtown LA.
  • Lunch at Cole’s.
  • Drinks at The Falls bar.
  • Uber from Wyatt & Magnolia’s to LAX.
  • Met all the Frenzels at the gate.
  • Flew 9 hours and 25 minutes!
  • Went through border control @ Oslo Gardermoen Airport
  • Flew 2 hours!
  • Arrive at Prague Airport.
  • No ubers at 10pm, so we took a taxi (only 675czk = $28)
View from our hotel room!
  • Late dinner sandwiches at fast food place by the Charles Bridge.
  • Randomly stumbled into Bar Legend 13 underground bar. Small place, but fun.

Tuesday, September 22nd - First day in Prague

  • Hotel Breakfast
    • Alley of shops
    • Prague Castle Dungeon
    • Beer with the Frenzels
    • Cathedral
    • Palace
Kayla in front of the Cathedral @ Prague Castle
View from Charles Bridge (That's the castle in the background)

  • Looked at the astronomical clock and spent some time on the big square.
    • Watched goofy Finnish street performer doing juggling tricks.
  • Bought tickets for a classical music concert at the Cathedral of St. Clement
  • Visited O’Che’s - a very weird Che Guevara-themed Irish Pub.
Tyler, Kara, Justin, me at O'Che's
  • Concert at the Cathedral of St. Clement
    • String quartet + cathedral organ (awesome!)
    • Ave Maria
    • Vivaldi’s Four Seasons
    • Random Bach, Beethoven, and others...
    • Sketchy host, clearly predatory towards tourists.
    • Bill had tax + service included, but illegally stated that service was not included.
From left: Magnolia, Tyler, me, Brandon, Hannah, Justin, Kara, Wyatt
  • Taxis to Vinárna U Sudu, underground cellar bar across the river.
    • Labyrinthine, several underground chambers.
    • Very very smoky, all of our clothes smelled like cigarettes afterwards.

Wednesday, September 23rd - Travel day to Munich, with a stop in Plzen

  • Hotel breakfast
  • Tram to Praha Hl. N.
  • Our only fancy train – SC 512 Pendolino -  Prague to Plzen
    • Free champagne, water, coffee, and sandwiches.
    • No other train we went on after had such service :(
Nice train!
    • Giant copper fermentation tanks
    • 9km of underground cooling/aging tunnels.
    • Delicious unfiltered, unpasteurized Pilsner from oak barrels.
    • Brewery Tour ran late, so we had to rush back to the train station.
  • Confusion over train numbers, jumped on EC 352 (actually EC 350) to Munich.
  • Train runs over an hour late.
  • Tried to get Uber, a driver named “Elvira” cancels. :(
    • Hilariously, another time Wyatt & Magnolia tried to get an uber, they got the same driver and she canceled on them again!
  • Met Sandra, our awesome AirBnB host, drop stuff off at the apartment.
    • Super comfortable place to stay, the neighborhood (Schwabing West) was cool too.
Our street in Munich
  • Ate a delicious dinner at the Italian Restaurant Mediterranee by our apartment.

Thursday, September 24th  - Oktoberfest!

  • Uber to Marienplatz, met the Duddy’s, Cliff, and associated party.
  • Beers at the Augustiner Restaurant near Marienplatz.
  • Walked, then took a free metro to tent area
  • Oktoberfest!
    • Eat/drink at a table at Paulaner tent for a long time
This is what Oktoberfest looks like.
    • Everyone separates
    • Ferris wheel with Wyatt & Magnolia.
On the Ferris Wheel. Oktoberfest is a giant carnival with BEER.
    • Found Frenzels, ended up in a different tent - Schützen-Festzelt
    • Drank heavily
    • Taxi back to apartment

Friday, September 25th - Relaxing in Munich

The design museum exhibits were awesome.
Fun with shutter speed @ Cafe BarCelona
The bookshop was fun.
Thali @ Restaurant Sitar

Saturday, September 26th – Travel day to Zurich + The Island of Lindau

  • Splitting up with Wyatt & Magnolia - they went to Budapest instead of Zurich.
    • Had to reroute Wyatt & Magnolia through Salzburg due to migrant crisis/border control.
  • Cleaned up/left keys for Sandra.
  • Delicious breakfast at Café Joon on Theresienstrasse.
Tiny cactus at Cafe Joon
  • Metro to Munich Hbf
We saw military vehicles being transported by train through Germany
  • Nice train to Lindau Hbf.
    • It’s a train station on an island! awesome!
  • Lunch at Eddi’s Pizza.
  • Wandering around.
St. Stephan's Church on Lindau
Relaxed dinner on Lindau

Sunday, September 27th – Zurich is expensive!

Baked egg thing!
    • Cool Alois Carigiet exhibit
    • Stained glass & religious artifacts exhibition
    • Photography exhibit showcasing working classes across time
    • Archeology exhibit had fascinating artifacts from pre-historic Zurich-area people.
At the Zurich National Museum
  • Walk to old town/Altstadt.
  • Lots of wandering around, kept being amazed at how expensive everything is.
    • We had Alpine Venison & Wild Boar!
  • Walked around Zurich Hbf train station (pretty much a mid-sized mall)
  • Went to Migros Market for groceries, one of the few local markets open on Sundays.
We ate in our hotel room a lot on this part of the trip.

Monday, September 28th – Lake Zurich ferry, gallery

  • Market breakfast in the hotel room (instant coffee, cold cuts, croissants)
  • Lake Zurich Ferry tour (free with our Eurail passes)
    • Ferry goulash & beer (20CHF = $20, yikes)
Lake Zurich was cold!
Damien Hirst @ Vertes Moderne
  • Street food lunch (Doner Kebab & Sandwich)
  • Dinner with Alex's sister Erin at her apartment (around Oerlikon neighborhood).
    • Thanks for the chicken soup and the good conversation!
Erin's roommate painted these.

Tuesday, September 29th – Last day in Zurich, zoo, running out of francs

  • Visited the Zurich Zoo.
    • Indoor rainforest biodome was incredible.
    • Amazing (and fairly happy looking) family of elephants with a very large area.
    • Very open, you can see many animals up close.
    • 52CHF = $52 for the two of us… ouch. :(
Baby elephant at the zoo!
  • Went to Beers’n’More upon Erin’s recommendation. Awesome beer shop run by an Irish-born Ethiopian.
    • Bought beer liquor.
  • In the evening, went to Pizzeria Scala in the Italian quarter.
    • Could only afford the cheapest pasta entrees and the cheapest wine :(
    • 80CHF = $80, ouch. :(

Wednesday, September 30th – Travel day from Zurich to Vienna

  • Tram to Zurich Hbf
  • Relaxed at the Zurich Hbf first class lounge (very nice, free with our Eurail passes)
  • Train from Zurich Hbf to ZRH airport.
  • Germanwings flight from ZRH to DUS airport (Dusseldorf).
Germanwings plane goodies.
  • Delayed Germanwings flight from DUS to VIE airport.
Flying over Dusseldorf!
  • Train from VIE to Praterstern Hbf.
  • 20 minute walk to Vienna Inn Apartments.
    • Saw a probable drug deal happening in an alcove.
    • Graffiti on the side of a building said: “All refugees are welcome!” with an anarchy symbol next to it.
  • Sketchy check-in to a Soviet-style decrepit 70’s/80’s apartment building, had to call for late night lockbox keycode, everything was closed.
  • Uber from apartment to Bodeguita El Pulpo, fantastic little restaurant, where we met back up with Wyatt & Magnolia after they had Hugarian adventures in Budapest.
  • After dinner, went to The Match Box - small bar with funny music videos. Cheap drinks.

Thursday, October 1st – Slightly disappointing first day in Vienna

  • Quick market breakfast.
    • Delicious Berliners!
    • Very disappointing - few real artifacts, all documents are bad replicas, very small, kind of expensive for what it is.
    • Coolest part was ringing the bell to get in.
Disappointing :(
  • Tried to go to the Josephinum, but it was closed :(
  • Lunch at Küche 18 - good Chinese food.
  • Uber to the Augarten (allegedly huge 17th century baroque garden with a palace in it)
    • Very disappointing as well, basically a huge park, lots of families with kids.
    • A couple of abandoned flak towers (impressive, but boring)
    • Couldn’t find the palace (seriously!)
Large and useless.
  • Went back to the hotel frustrated, day was kind of a bust.
  • Somewhat swanky, very nice Da Capo Restaurant for dinner.
Even the bathroom door in Da Capo was fancy.
  • Afterwards, wandered over to Blue Bar, a locals spot nearby.
    • Got approached by a very drunk Viennese guy who introduced us to his friends, then got too drunk and left.
    • We ended up talking with a local student nurse named Anna who was 19 years old and very jovial. She also chain smoked her hand-rolled cigarettes the ENTIRE TIME. (Probably smoked half a pack worth in 3 hours). She also bought us a round of some sort of peach schnapps shots.

Friday, October 2nd – Better time in Vienna

  • Kayla prepared a local breakfast with groceries from the previous day in our apartment, and we enjoyed it with Wyatt & Magnolia.
  • Walked to Praterstern Hbf
  • Train to Vienna Central Cemetery
    • Incredible, huge, and beautiful. Tons of giant sculptures and crypts.
    • Famous classical composer graves - Beethoven, Schubert, Brahms, etc…
Beethoven's grave.
  • Afterwards, found a fantastic restaurant called Schloss Concordia in an old building.
    • Incredible schnitzel.
Schloss Concordia
  • Train back to Vienna, got off at the central station.
  • Walked to the First American Bar.
    • Only got a couple of drinks, didn’t realize it was happy hour so everything was half off.
    • Had Austrian Trumer Pils!!! (Seemed slightly different from the Berkeley clone)
  • Wyatt & Magnolia went back to their hotel, but Kayla and I kept walking and ended up at the Onyx Bar on Stephansplatz.
    • Kayla and I were slightly underdressed, it was very fancy.
    • Beautiful views, and even though the bar was packed, one of the servers managed to find us a seat by a window, where we enjoyed our drinks for a bit.

Saturday, October 3rd – Travel Day to Prague

  • Check out from Vienna Inn Apartments
  • Uber to Praterstern Hbf
  • S train from Praterstern Hbf to Vienna Hbf
  • Relaxed at the Vienna Hbf OBB First Class Lounge
  • Kayla bought new shoes for 9 euros because her Converse were falling apart.
  • Railjet train (they go 150mph!) from Vienna Hbf to Prague Hl. N.
  • Metro from Prague Hl. N. to Mustek station.
  • Check into Hotel Modrá Růže.
  • Tried to get a reservation at Čestr Restaurant, but we were pretty late so ended up reserving for the following day.
  • Dinner at Kolkovna Restaurant.
    • Wyatt got the giant platter with three kinds of meat and almost finished it.
    • Finished off with plum/pear brandy shots (Slivovice/Hruškovice in Czech)
Classic Pilsner ad in Kolkovna
  • Wandered around Staré Město.
  • Decided to go back to hotel and drink at the bar.
  • Spent the rest of the evening at the hotel bar.
    • The bartender was extremely drunk and jolly, celebrating his Name Day (imieniny). His English was pretty bad, but between my Russian and low-level Czech, we figured out most of what he was saying.
    • He gave us two rounds of free shots of Slivovice his uncle had made at home (essentially 71% alcohol plum moonshine), then convinced us to drink a final round of beers with him. He was also taking photos with a table of middle aged ladies next to us who were also pretty drunk.
    • At the end of the night, he quietly slipped us some free marijuana, which surprised us since it’s less common in Europe.

Sunday, October 4th – Prague & The Bone Church @ Kutná Hora

  • Hotel breakfast (pretty good, but not as great as Hotel Constans on the first leg)
  • Given that our trip was concluding, and the fact that Prague was a cheap city, I resolved to find a new messenger bag/briefcase for work trips, since my existing one was proving too small. We walked around a bunch of stores but didn’t find what I wanted.
  • Visited the delightfully campy and silly Torture Museum.
Ouch
  • Walked to the train station.
  • Train from Prague Hl. N. to Kolin.
    • Rushed but delicious train dining car lunch. Were surprised to find that they partially cook the food on the train itself.
  • Train from Kolin to Kutná Hora.
    • Very very rural area.
    • Kutná Hora train station was in the middle of nowhere.
Rural Czech Republic
  • Walked about a mile to the Sedlec Ossuary.
    • Mind blowing and somewhat creepy place.
    • Bought a bunch of tiny skull-related souvenirs.
These are all REAL human bones.
  • Train back from Kutná Hora to Prague Hl. N.
  • Went to dinner at Čestr Restaurant. Cool menu, great food.
  • Finished the day at the Zombie Bar, which was pretty much empty.
    • Overwhelming list of cocktails.
  • Back to the hotel.

Monday, October 5th – Last day in Prague, and the trip as a whole - beer spa!

  • Hotel breakfast.
  • We wanted to go visit the BeerLand Spa, but unfortunately found out online that everything was booked 3 days ahead. As a last effort, we called the spa directly and they found us a free slot (with the sauna room!) at 2:00pm. Lucked out!
  • Kayla and I went bag shopping for me and after wandering the giant Palladium mall, I finally found one at a Domi/Samsonite store. Hooray!
  • Brunch at the Grand Café Orient.
    • Really good smoked salmon tartare.
    • One of the highlights of the trip. Wish we could have done a two hour session.
Terrible photo of a really good time.
  • Dinner at Agave Restaurant, figured it would be fun to try Mexican food in Europe.
    • Very good food… didn’t taste like Mexican food though. :-p
  • Walked to the Hemingway Bar for one last drink before an early night.
    • Fancy cocktails: Hibiscus Fairy & Aviation Collins
    • Wyatt & Magnolia left early because they were tired.
    • Kayla and I stayed for one more drink, and ended up talking for two hours to a couple of Irish ladies from around Belfast? Very friendly and interesting conversation.

Tuesday, October 6th – Fly back home

  • Woke up at 5:00am & checked out of the hotel.
  • Uber to PRG airport.
    • Hilariously slow due to low battery, driver was trying to save it. A little scary going 45mph on the freeway.
  • Flew 2 hours, from PRG to Stockholm Arlanda airport.
  • Wandered around, Sweden is expensive! 100SEK = $12, water bottles were 30-40SEK = $4-5!!!
  • O’Leary’s Restaurant in Stockholm airport.
  • Flew 10 hours from ARN to LAX.
    • New automated border control at LAX - computer takes your picture and scans your passport, then prints out a crazy looking receipt that you show to the agent. Weird.
  • LAX FlyAway bus to Union Station.
  • Dinner at Traxx Restaurant.
  • Uber back home!

Random Bits, in no particular order

  • Prague was incredible in every way: easily walkable, good public transportation, cheap, beautiful, modern, old, cosmopolitan, great food, fantastic hotels, fantastic service, great people.
  • Munich was great as well: felt familiar, easy to navigate, modern, good public transportation, affordable, kind people, great food.
  • Zurich felt very fancy and extremely cosmopolitan. It also had great food and was easy to navigate. Zurich was also incredibly expensive, everything being almost triple (sometimes even more) than the other cities we went to, and about double USA prices.
  • After learning some German and getting comfortable with basic day-to-day stuff, Swiss German makes no goddamned sense.
  • Vienna had inconvenient public transportation, sketchy neighborhoods, and a lack of sights other than museums. It also felt somewhat economically depressed.
  • Our Eurail passes worked out very well, and taking first class trains everywhere was comfortable and convenient. The first class lounges in the stations were very nice and comfortable to relax in. If we had bought first class train tickets for all the journeys we took, we would have spent over a thousand dollars easily.
  • Huge thanks to Carrie’s dad for covering our nice dinner in Munich.
  • Huge thanks to Erin for cooking us dinner in Zurich.
  • Getting around by train in Europe was easy and pretty comfortable.
    • Google Maps was usually pretty good with figuring out local public transportation and mostly ok with walking directions, but it was AWFUL with regional/cross-border trains. Wrong schedules, missing lines/stops, etc… We ended up utilizing the local train system sites exclusively because they were much more efficient and accurate.
    • SC (SuperCity) trains in the Czech Republic were the nicest, we only rode one. Free champagne, water, coffee, and sandwiches in first class, as well as good free WiFi.
    • RJ (RailJet) and ICE (InterCity Express) trains were the fastest, with nice first class and dining cars. Shitty WiFi usually.
    • IC (InterCity) and EC (EuroCity) weren’t fast, but also had nice first class and dining cars. Also shitty WiFi if there was any at all.
    • S Bahn, Regional, and other trains were generally the bare minimum. Roughly equivalent to Pacific Surfliner Amtrak in the states.
  • We got very used to the high quality European food. Less stomach issues compared to the states, even cheap street food was generally made with good ingredients. Coffee was amazing pretty much everywhere and made even high quality California coffeeshop pale in comparison.
  • We definitely saw some signs of World War II and other wars throughout Czech Republic and Austria (not so much the parts of Germany we were in). A lot of rural Czech & Austrian towns had large abandoned/bombed out factories. Passing by train through Brno in particular looked somewhat post-apocalyptic. Also a cabbie told us that some damage on the National Museum in Prague was from Soviet tanks in 1968.
  • Norwegian Air has a reputation for being hit or miss - either they’re efficient, fairly comfortable, cheap, and easy, or they cancel/delay flights, have non-existent customer service, and have a terrible refund policy. We got lucky on our trip and had no issues whatsoever with them, but who knows for next time.
  • Magnolia has a very severe peanut/lupine/legume allergy, and we were happy to discover that most of the restaurants we went to had allergen information right on their menus, and even if they didn’t, the waiters were always very understanding and did their best to make sure Magnolia was safe.
  • European airport security is different than the US - they’re not as strict with the body/clothing searches beyond a metal detector, but their bag X-Rays are very very thorough, and their agents check everything that looks even remotely suspicious. I don’t think a single European airport that we were in had us take off our shoes, unlike the US.
  • Communication/phone service was problematic. Given our experience last time, I opted to buy international SIM cards for Kayla and me to use in Europe. They’re pay-as-you-go and allegedly work better than roaming carriers. I used KnowRoaming and Kayla used OneSimCard since she has a CDMA/GSM phone on Verizon and KnowRoaming doesn’t support it.
    • We both paid roughly $150-175 over the course of the trip, using almost exclusively data, communicating using Facebook Messenger.
    • Making calls was OK, but there was a callback process and the connection had a huge delay.
    • I could send and receive SMS messages (though it was very slow), but Kayla couldn’t send any (awful!)
    • Wyatt & Magnolia had the best service - they use T-Mobile and seem to have the best overall phone experience, even back in the states.