home-service
This workspace contains a Home Assistant gRPC gateway and the protobuf contract it serves.
The current implementation is centered on ha-gateway, a Go service that:
- exposes Home Assistant operations over gRPC
- translates gRPC requests into Home Assistant REST API calls
- emits OpenTelemetry traces and metrics when configured
- keeps protobuf definitions and generated Go stubs in-repo
EntityService and LightService are implemented. SwitchService and
EventService are scaffolded but currently return Unimplemented.
Workspace Layout
.
├── proto/ # Source protobuf definitions
├── gen/ # Generated Go protobuf/grpc code (committed)
├── ha-gateway/ # Go gRPC server
├── buf.yaml # Buf module config
├── buf.gen.yaml # Buf codegen config
└── go.work # Go workspace linking gen + ha-gateway
Architecture
ha-gateway follows a ports-and-adapters structure:
internal/core/domain: pure domain typesinternal/core/ports/driving: interfaces exposed to primary adaptersinternal/core/ports/driven: interfaces the app layer depends oninternal/app: application logic for entity and light operationsinternal/adapters/primary/grpc: gRPC handlers and proto/domain mappinginternal/adapters/secondary/ha: Home Assistant REST clientinternal/telemetry: OpenTelemetry setup
The runtime flow is:
- A gRPC client calls
EntityServiceorLightService. - The gRPC adapter maps protobuf messages into domain parameters.
- The app layer orchestrates the use case.
- The HA adapter calls Home Assistant's REST API.
- The response is mapped back into the protobuf response.
Services
Implemented
ha.v1.EntityServiceGetStateListStates
ha.v1.LightServiceTurnOnTurnOffToggle
Stubbed
ha.v1.SwitchServiceha.v1.EventService
The event path is planned around Home Assistant WebSocket subscriptions, but the WebSocket adapter and fan-out broker are not implemented yet.
Configuration
ha-gateway reads configuration from environment variables. A sample file lives
at ha-gateway/.env.example.
| Variable | Required | Default | Notes |
|---|---|---|---|
HA_TOKEN |
yes | none | Home Assistant long-lived access token |
GRPC_PORT |
no | 50051 |
gRPC listen port |
HA_BASE_URL |
effectively yes | empty | Example: http://ha.home.arpa:8123 |
OTEL_ENDPOINT |
no | empty | OTLP gRPC endpoint; empty disables telemetry |
Notes:
- startup fails if
HA_TOKENis missing HA_BASE_URLis not validated on load, but the gateway cannot reach Home Assistant without it- if
OTEL_ENDPOINTis empty, the service installs no-op telemetry providers
Prerequisites
- Go
1.26 buffor protobuf generation- a reachable Home Assistant instance
- a valid Home Assistant long-lived access token
Generate Protobuf Code
Run from the repo root:
buf generate
Generated files are written to gen/ha/v1.
Build
Sync the workspace, then build the gateway:
go work sync
cd ha-gateway
go build ./...
Run Locally
Create a local env file:
cp ha-gateway/.env.example ha-gateway/.env
Fill in HA_TOKEN and HA_BASE_URL, then start the server:
cd ha-gateway
go run ./cmd/gateway
The gateway listens on :50051 by default.
Smoke Test With grpcurl
Examples against a locally running gateway:
# List all light entities
grpcurl -plaintext -d '{"domain":"light"}' \
localhost:50051 ha.v1.EntityService/ListStates
# Get one entity
grpcurl -plaintext -d '{"entity_id":"light.living_room"}' \
localhost:50051 ha.v1.EntityService/GetState
# Turn on a light at 80% brightness
grpcurl -plaintext -d '{"entity_id":"light.living_room","brightness_pct":80}' \
localhost:50051 ha.v1.LightService/TurnOn
# Toggle a light
grpcurl -plaintext -d '{"entity_id":"light.living_room"}' \
localhost:50051 ha.v1.LightService/Toggle
Docker
Build from the repo root:
docker build -f ha-gateway/Dockerfile -t ha-gateway:dev .
Run it with the same env file:
docker run --env-file ha-gateway/.env -p 50051:50051 ha-gateway:dev
Telemetry
When OTEL_ENDPOINT is set, the gateway exports:
- traces via OTLP/gRPC
- metrics via OTLP/gRPC
The service name is ha-gateway. When OTEL_ENDPOINT is unset, telemetry is
disabled for local development.
Current Limitations
- no authentication/authorization on inbound gRPC requests yet
SwitchServiceis not implementedEventServiceis not implemented- Home Assistant event streaming over WebSocket is not implemented
- there are currently no unit tests in the repo
The auth note in ha-gateway/cmd/gateway/main.go explicitly calls out API-key and mTLS as future options before exposing the gateway outside a trusted network.