Skip to main content
Featured
Completed
Iot

Zimi Smart Home Voice Assistant Integration

Certified Alexa and Google Home control for Zimi devices from one domain layer — platform-specific translators, OAuth linking, and report-state from live telemetry.

2019-2021
Zimi Ltd
Senior Backend Engineer - Voice Integration
Zimi Smart Home Voice Assistant Integration project showcase - Certified Alexa and Google Home control for Zimi devices from one domain layer — platform-specific translators, OAuth linking, and report-state from live telemetry.

Technologies

  • TypeScript
  • Express
  • OAuth2
  • Google Actions API
  • Alexa Smart Home API
  • Node.js
  • MQTT
  • JWT
  • REST APIs
  • Event-driven Architecture

Key Achievements

  • Certified Alexa Smart Home and Google Home fulfilment
  • One device/command model behind two assistant APIs
  • Report-state from the telemetry path so assistants are not polling us

Project Links

I built and certified Zimi’s Amazon Alexa and Google Home integrations so the same in-wall devices can be asked to switch, dim, and report state from either assistant. Fulfilment runs on our GCP backend. Assistants never talk MQTT.

Voice, OAuth linking, and report-state are views in the C4 model.

Two assistant APIs, one device model

Google Sync/Query/Execute and Alexa Discover/Control/ReportState are the same three questions in different envelopes: what devices exist, what are they doing, do this.

If each assistant gets its own stack, those answers drift. A dimmer grows a trait on Google and not on Alexa. Certification becomes two products. Multi-function hardware makes that worse: one physical plate is a switch, a dimmer, a fan, a garage — virtual endpoints with different capabilities.

Auth is a second split. App users have IdP JWTs. Voice needs OAuth account linking, with the assistant holding tokens that must never be treated as an admin session.

And state has to move both ways. A finger on the wall should update the Google Home graph. A spoken command should go through the same MQTT command path as the mobile app, or “Alexa off” and the app will disagree.

What changed

I put a translation layer on each assistant and a shared domain layer behind both.

Google and Alexa adapters map discovery, query, and execute into a common request: who is the user, which endpoints, which operation. The domain layer checks the linked account, loads devices, and runs the same command/query code the rest of the platform uses. Responses map back into each assistant’s payload shape.

OAuth account linking is the identity bridge. The voice path does not accept the customer app JWT. Tokens and unlinking (Google Disconnect, Alexa disable) are first-class.

Unsolicited changes — someone used the wall switch — already flow through the telemetry processor. That processor reports state to Google Home Report State and Alexa Change Report. Assistants are not polling us for “is the light on.”

Alexa hits a thin wrapper; fulfilment, state, and commands stay on GCP. Device-class mapping (switch, dimmer, fan, outlet, blind, garage) lives in the shared model so both certifications see the same hardware.

Translate at the edge, share the domain

The alternative was two fulfilment services. That duplicates ownership rules, endpoint IDs, and “what does off mean on a fan.” The cheaper-looking option is the one that fails certification when Google adds a trait and Alexa does not.

Keeping the assistants at the edge means a Google payload never leaks into command execution. The domain layer speaks our operations. Adding a third assistant, if we ever did, is another translator — not another device model.

The operational consequence is that report-state is part of telemetry, not part of the HTTP request that handled the last voice command. If we only updated assistants when voice ran, wall-switch changes would be stale until the next spoken query. Users notice that immediately; they call it “broken.”

After

Both platforms certified. A household can link once per assistant and control the same devices the app sees. Capability mapping is shared. State follows the device, not the last voice request.

Related: partner API (OAuth and events for non-voice partners), migration, C4 voice and identity views.