A Google Nest Hub and a Google Pixel Tablet as touch panels

Christian Drexler

We just moved, and the first afternoon in the new flat went into the Wi-Fi. Once both mesh points were up, I asked for a list of everything on the network. Two screens were on it that I had never done anything with: a Google Nest Hub on my office desk and a Google Pixel Tablet on its dock in the bedroom. Both show a photo slideshow all day.

So the question was simple: can they show something useful instead? By the next morning the Hub was a light switch for my office and the tablet was a bedside panel. Neither needs an app or a smart-home platform.

The trick: Cast a web page, then tap it

A Google Nest Hub is a Google Cast receiver, just like a Chromecast. Cast normally plays video, but there is a small open-source receiver app called DashCast that loads any URL full screen. In Python, pychromecast ships a controller for it:

import pychromecast
from pychromecast.controllers.dashcast import DashCastController

cc = pychromecast.get_chromecast_from_host((HUB_IP, 8009, None, None, None))
cc.wait(timeout=20)
dc = DashCastController()
cc.register_handler(dc)
dc.load_url("http://<machine-on-the-lan>:8765/", force=True)

The part I was not sure about was touch. Cast is meant for watching, so I expected the Hub to swallow taps or show its own "stop casting" controls. I put a big TAP ME button on the screen that logged every tap back to the Mac. The taps came through. That turns the Hub into a small touch screen that shows whatever page I serve on the home network.

The Google Pixel Tablet does the same thing, but only when it sits on its dock. Off the dock it is a normal tablet and does not offer Cast at all. On the dock it switches to hub mode and shows up as a Cast screen like the Nest Hub.

What is on the two screens

Office, Google Nest Hub: the two Elgato Key Lights on my desk. Four presets across the top (Call, Work, Evening, Off), then one card per light with an on/off switch, a brightness slider and a warmth slider. It refreshes every few seconds, so a change made from the Elgato app shows up there too.

Bedroom, Google Pixel Tablet: the time, very large, on the left half. That was the actual wish: a clock you can read from bed. On the right are the AC (power, minus/plus, mode) and one large button for the hot water. Along the bottom is a row of buttons that do nothing yet (ceiling, night light, curtains, front door, alarm, good night). They light up and say "not connected yet". That way I can see whether we would use a button before I wire it up.

The AC buttons wait a second after your last tap and then send everything together. Three taps on plus is one command, not three.

Three things that went wrong

Every tap counted twice. On a touch screen one tap fires a touch event and then a click event. My test page listened for both. Easy to fix, but then...

The fix did not show up. The Hub kept the old page. DashCast holds on to whatever it loaded, and loading the same URL again did not refresh it. What works is to close the DashCast app on the device first, wait three seconds, and load the URL with a timestamp on the end. The cast step now always does that.

The tablet is slow to start. The Hub brings DashCast up in about ten seconds. The tablet sometimes needs thirty. The first version gave up too early and reported a failure while the page was still loading. The cast step now waits up to thirty seconds before it calls anything a failure.

The browser does not talk to the lights

The page in the Hub does not call the Key Lights directly. The lights have a small HTTP API on the home network, but they do not answer browser requests from another origin. So the page talks to a tiny Python server, and the server talks to the lights, the AC and the hot water. One server, two pages, a few JSON endpoints.

The hot water needs a note of its own. It is an old wall switch with a little robot finger on it that presses the switch. In press mode, on and off are the same press. The panel can only assume each tap flips it. If someone uses the switch by hand, the panel shows the wrong state until the robot is set to its proper switch mode.

Why it ended up on a Raspberry Pi

The first version ran on my laptop. That works until the laptop sleeps, and then both screens freeze. An always-on machine fixes that, and there was an old Raspberry Pi 1 in a drawer. It is a single core with 512 MB, far too weak for Home Assistant, but it has no trouble serving two small pages and passing on a button press.

It runs two services that start at boot and restart if they crash: the panel server, and a keeper that checks both screens every three minutes. If a screen has fallen back to its photo slideshow, the keeper casts the panel again. If someone is casting a video, it leaves the screen alone. Without the keeper the panels would be gone after the first reboot or idle timeout, and nobody would put them back.

Two small things from the Pi setup:

  • Python wheels do not build on the old ARM chip. The libraries that need compiling (cryptography, zeroconf, protobuf) came from the system package manager instead of pip. The virtual environment uses them with --system-site-packages.
  • A login that refreshes itself can only live in one place. The AC goes through a cloud account whose token renews every two hours. With the laptop and the Pi both holding it, each renewal logged the other one out. The token now lives on the Pi only, and the laptop sends AC commands through the Pi.

What it cost

Nothing new was bought. Two screens that were already in the flat show something useful now, and the drawer is one Raspberry Pi emptier. The next candidate is an old first-generation Echo Show. It has no Cast, so it gets a bookmark in its browser instead, and its taps should work the same way.