Dr. Smart Home Boldly Goes Where No Sonos Has Gone Before

How a free text-to-speech hack turned my Sonos Beam into the computer from the USS Enterprise


Dev Team Drops Another Unreleased FW

This story starts the way Dr. Smart Home stories often start: with a beta firmware release for my 1Home Server landing in my lap.

And it was a big one. Possibly the biggest update in a long while. New icons in the dashboard (personally I liked the old ones a little better — but I'll admit the new ones look soooooo good in the upcoming new 1Home app. Hint. Hint.), 1Home Touch support, SIP doorphone support, and — finally — Air Quality sensors over Matter.

That last one I have been waiting for since the day IKEA released the ALPSTUGA sensor and I discovered I couldn't pull it into 1Home. Which also meant my proper Sonos, Inc. integration testing kept getting postponed, because the automation I actually wanted to build was: play a sound when the CO2 in the room gets too high.

So that's exactly what I set out to do this time.

Why a Beep Wasn't Enough

There are all kinds of sounds in the 1Home Sonos library. I could have picked a chime, wired up the trigger, and called it an afternoon.

But sitting there thinking about the problem, I wanted more. I wanted my home to talk to me — like a Galaxy-class starship from Star Trek.

There's a serious point underneath the nerdery. I've genuinely believed for years — and pitched this inside 1Home more than once — that voice communication between a user and their smart home shouldn't be one-way. Right now it's almost always the user talking to the home. It should be bidirectional.

Because telling people things out loud is still the single best way to make sure they actually learn them. Especially people who aren't fluent in smart home apps, touchscreens, and push notifications. If the home just says it, everybody in the room knows what's going on and where to look.

Exactly like Star Trek.

Aljaž Raises the Stakes

My initial plan was modest: record a few warnings myself (or AI-generate them), drop them on GDrive, generate links, wire up the triggers, done.

Then I excitedly explained the plan to Aljaž (CPO at 1Home), who immediately wanted to take it further: find a free text-to-speech API and generate the audio files on the fly. No pre-recorded library. The home composes what it needs to say, when it needs to say it.

Naturally, I loved the idea and started playing with it immediately.

The FreeTTS Detour (Or: Where Dr. Smart Home Loses His Patience)

My research — and to be fair, Claude's — pointed to FreeTTS.org as the best candidate. A proper REST API, 400+ neural voices, free of charge, and best of all: no API key required. Exactly what I needed.

First job was to build the message. That part was easy: a simple if / else structure plus string.format inside the Lua block in 1Home Automations. Read the CO2 value from the sensor, decide which of three states we're in, assemble the sentence. Below 800 ppm, say nothing. Between 800 and 1200, a polite nudge. Above 1200, open a window, now.

Then I called the API.

403.

I tried again. 403. I changed the headers. 403. I added an explicit Content-Type. Still 403. I turned off SSL verification, which in hindsight was me flailing. 403.

Somewhere around this point there was some genuine tension between Dr. Smart Home and his assistant Claude, who kept confidently blaming the API while I kept insisting the problem was on our side. (For the record: sometimes it was on our side. %v works in log.info but not in string.format, which cost us one very silly runtime error. Lesson learned.)

I'm not going to pretend I know exactly what was happening on their end. What I do know is that I couldn't get the API to do what I wanted, the way I wanted, free of charge — and I wasn't about to start paying a monthly subscription to tell my own living room to open a window.

So I went and tried the service directly on their website instead, just to hear what the voices actually sounded like. They sounded great. Right up until the end of the clip, where a cheerful "Generated with FreeTTS" was stapled onto my message.

That was the moment I stopped. Imagine the USS Enterprise warning you about a hull breach and then reading out a sponsorship credit. Absolutely not.

The Solution Was Hiding in Plain Sight

Back to the drawing board, and this time I started from the constraint instead of from the feature list.

The 1Home Sonos action block needs an URL. A plain link that Sonos can go and fetch by itself. That's the whole requirement, and it's stricter than it sounds, because most TTS services I found are built around a different assumption: you send them text, they send the audio straight back to whoever asked. Great if you're a website or an app that wants to play it immediately. Not great if the thing that needs to hear it is a speaker on the other side of the room.

Which meant I didn't need a service that generates a file and then parks it somewhere for me. I needed one where the URL itself is the audio.

And that thing already exists, has existed for years, and is what Home Assistant users have quietly been using the whole time: Google Translate's text-to-speech.

You know the little speaker icon in Google Translate that reads your text out loud? That's a plain GET request. Feed it a URL shaped like this:

https://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&tl=en&q=Your+message+here

...and it hands back an MP3. No POST. No API key. No account. No signup. No watermark. Nothing to authenticate, nothing to rate-limit me out of, and also no HTTP call from my Lua script at all.

The script's entire job collapsed down to: read the sensor, pick the sentence, glue it onto the end of that URL, and hand the URL to Sonos. Everything else is delegated: Google generates the audio, Sonos plays it.

There was one small wrinkle. The message has to be URL-safe — spaces can't stay spaces, and punctuation needs escaping. The fix was almost embarrassingly simple: write the messages URL-safe in the first place. Spaces as +, no commas, nothing exotic. The only dynamic part of the sentence is the CO2 number, and digits are always safe.

So the string goes to Google Translate, Google Translate serves the MP3 at that URL, the Action block passes the URL to my Sonos Beam, aaaaaaannnnnddddd —

The USS 1Homior Is Now Operational

"Attention. CO2 levels are elevated at 900 parts per million. Consider ventilating the room."

My living room said that. Out loud. In a calm, slightly synthetic voice, from the Sonos Beam, because a Matter air quality sensor noticed the air was getting stale.

I am aware that to a neutral observer this is a mildly robotic voice reading a number off a sensor. To me it is a childhood dream with a firmware version number.

Next on the Mission Log

This is just the beginning. The pattern is fully generic now — any sensor state, any sentence, any speaker. The hard part is done; what's left is deciding what's actually worth saying out loud.

Already on the list:

  • Front door left unlocked
  • Humidity drifting out of the comfortable range
  • Window open while the heating is running
  • Somebody's at the gate (now that SIP doorphone support is in) - this would be especially interesting if it was possible to detect who is at the door then announce that person

The trick, I suspect, will be restraint. There's a very fine line between a starship computer and a house that nags. Nobody on the Enterprise ever had to listen to the ship announce that the humidity in Cargo Bay 3 was three percent below optimal. The ship spoke when it mattered, and the rest of the time it had the good manners to shut up.

So: sensors, sentences, and a firm hand on the volume of the thing.

The USS 1Homior has left dry dock. Warp two, and mind the CO2.

Dr. Smart Home out. If you want the whole script/automation - let me know. And stay tuned for more Lua script shenanigans.