Skip to main content
Open Source

The App Is Not the Device

You bought the hardware. They kept the app — and made it the only way to use it. We got tired of that, so we reverse-engineered two cloud-locked gadgets — a car remote-starter and a hot tub — into plain local HTTP you can wire into any smart home, and open-sourced both under MIT. Here's the story, the lessons, and why it's the same fight we pick every day.

Reverse EngineeringHome AssistantLocal ControlNo AccountMIT

You Bought the Device. They Kept the App.

A remote car-starter you paid an installer to wire in. A hot tub sitting in the backyard. Both yours. And both come with a mandatory phone app that is the only sanctioned way to use them — no API, no web page, no way to say "do this when X happens." The starter's app in particular is a lonely 1.9-star affair, and there is no "Hey Assistant, start my car" because the vendor never shipped one.

That's the pattern with almost every connected gadget now: the hardware is yours, but the control plane is rented. The app is a fence around a device you already own. So we did the obvious thing and climbed it — for interoperability, with hardware we own.

So We Talked to the Cloud Ourselves

The car starter (Fortin EVO-START LTE)

A rebadge of the Chinese "hyll" / ZXY268 telematics platform. Decompiling the app revealed a plaintext-TCP protocol: an 8-digit length prefix, a JSON envelope, and an HMAC-SHA1 signature, to a region-sharded command server. Log in with your own account, sign the frame, send code 303120 — the engine turns over.

The hot tub (Bestway SmartSpa, AIRJET V02)

An anonymous-"visitor" API on an AWS backend, with AES-256-CBC-encrypted commands. You bind it by scanning the app's own Share Device QR code — no proxy, no cert-unpinning. The protocol work here is thanks to epheterson/bestway-spa-v2; we ported the runtime to Node and added the smart-home layer.

Each becomes a tiny self-hosted relay that keeps a session warm and exposes the device as a token-gated local HTTP API. From there it's just a request:

your gadget, as a plain endpoint on your own network
# the car
$ curl "https://home.example.com/cmd/start?token=..."   # engine on
# the hot tub
$ curl "https://home.example.com/cmd/set?token=...&temp=38"  # warm it to 38°C

Anything that can make an HTTP request can now drive the device — a script, a cron job, Home Assistant, or an AI agent.

One Integration, Every Ecosystem

We deliberately did not build this for one assistant. The relay is just an HTTP API, so the cleanest path is Home Assistant: point HA at it with a few lines of rest_command and you inherit everything HA already bridges to — dashboards, automations, voice assistants, HomeKit — without picking a side.

configuration.yaml
rest_command:
  car_start: { url: "https://home.example.com/cmd/start?token=..." }
  spa_heat:  { url: "https://home.example.com/cmd/set?token=...&heat=on" }

A native cloud-to-cloud integration is included too, as one optional path — but the point is that the device is finally yours to point anywhere.

What We Learned (So You Don't Rediscover It)

The reverse-engineering was the easy half. Getting a homemade device accepted by a smart-home platform is where the bodies are buried. A few that cost us real hours, now written down in each repo's LESSONS.md:

One bad device fails the entire sync

A single malformed device in a smart-home SYNC makes the platform reject the whole list — including the devices that already worked. Add capabilities one kind at a time.

You can't unlock a lock from an automation

Assistants block 'unlock' (and garage-open) as automation actions for safety. Want unlock behind a custom phrase? Model the lock as a plain switch (on = lock, off = unlock).

Use the textbook device type

A hot tub feels like a WATER_HEATER, but that type was rejected at link time. The canonical THERMOSTAT + a temperature trait linked on the first try. Don't get creative with the schema.

Linking has a ~5-second budget

Account-linking runs a SYNC and an initial QUERY, each within a few seconds. A cold round-trip to a distant cloud blew it. Serve device state from a warm in-memory cache; refresh in the background.

Two Repos. MIT. Yours.

Both are zero-dependency Node, run behind your own reverse proxy, and keep your credentials on your own box. If your gadget is one of these — or a sibling white-label on the same platform — you can be up in minutes.

Reminder from the repos: a remote start turns on a real engine — never in an enclosed space. Interoperate with hardware you own.

Why a Bitcoin-AI Company Wrote This

Because it's the same fight. Every connected gadget wants to sit between you and hardware you own — an account, an app, a login you can't remove. It's the consumer-hardware version of the wall we wrote about in The Identity Tax: the app isn't a technical requirement, it's a moat.

Sats4AI is the same idea pointed at AI tools. Your local model can now own its hands too: make a phone call, send a fax, narrate an audiobook — authorized by payment, not by an account. And the buyer doesn't have to be a human. An agent can discover a tool, check the price, pay a few sats over Lightning, and use it — the machine equivalent of turning a rented device back into one you control.

Free the toaster today; let your agent pay for its own tools tomorrow. Same principle, different rung.

Own the Device. Let the Agent Pay.

40+ real-world tools your agent can pay for with Lightning — no signup, no API key, no login endpoint. Authorized by payment, not by account.