5.0 KiB
home-services
home-services is a Go workspace for internal home-control services. It keeps
Home Assistant behind a gRPC gateway, adds an AI command gateway backed by
Ollama, and exposes both through a Discord slash-command bot.
Architecture
The services follow hexagonal architecture:
internal/corecontains domain types and portsinternal/appcontains use-case orchestrationinternal/adapterscontains gRPC, Discord, Home Assistant, Ollama, logging, and telemetry edges- dependencies point inward toward the app and core packages
Service flow:
Discord users
|
v
discord-bot -----> ha-gateway -----> Home Assistant REST API
|
v
ai-gateway ------> Ollama
|
v
ha-gateway
The protobuf contracts live under proto/. Generated Go code is committed
under gen/ and shared by all modules through the Go workspace.
Services
ha-gateway
Internal gRPC gateway for Home Assistant.
- Default port:
50051 - Talks to Home Assistant through the REST API
- Implements entity state lookup and discovery
- Implements light control and light discovery
- Implements switch discovery
- Stubs switch control and event streaming
- Supports optional mTLS when
TLS_DIRis set - Exposes gRPC health checks and reflection
See ha-gateway/README.md.
ai-gateway
Internal gRPC gateway for AI-assisted home commands.
- Default port:
50052 - Calls Ollama for intent extraction and model listing
- Calls
ha-gatewayfor light discovery and light actions - Caches light discovery results for prompt context
- Supports optional mTLS when
TLS_DIRis set - Exposes gRPC health checks; reflection is enabled in debug logs
See ai-gateway/README.md.
discord-bot
Discord slash-command process for home control.
- Registers
/light,/switch, and/aicommands - Calls
ha-gatewayfor direct Home Assistant commands - Calls
ai-gatewayfor free-form AI queries and model management - Supports optional mTLS for gateway clients when
TLS_DIRis set
Repo Structure
home-services/
├── ai-gateway/ # AI gRPC gateway backed by Ollama and ha-gateway
├── discord-bot/ # Discord slash-command bot
├── gen/ # Committed generated protobuf/gRPC Go code
├── ha-gateway/ # Home Assistant gRPC gateway
├── proto/ # Source protobuf contracts
├── buf.gen.yaml # Buf generation config
├── buf.yaml # Buf module config
└── go.work # Go workspace
Local Development
Prerequisites:
- Go
1.26+ buf, when changing.protofilesgrpcurl, for manual gRPC checks- Home Assistant with a long-lived access token
- Ollama, if running AI queries
- A Discord application and bot token, if running
discord-bot
Set up dependencies:
go work sync
Regenerate protobuf code after changing files under proto/:
buf generate
Run services in separate terminals:
cp ha-gateway/.env.example ha-gateway/.env
cd ha-gateway
go run ./cmd/gateway
cp ai-gateway/.env.example ai-gateway/.env
cd ai-gateway
go run ./cmd/gateway
cp discord-bot/.env.example discord-bot/.env
cd discord-bot
go run ./cmd/bot
Each service loads .env from its current working directory, so run commands
from the service directory when using the example env files.
Test And Build
Run tests from the workspace root:
go test ./ha-gateway/... ./ai-gateway/... ./discord-bot/...
Build service binaries from the workspace root:
go build ./ha-gateway/... ./ai-gateway/... ./discord-bot/...
Build container images from the workspace root:
docker build -f ha-gateway/Dockerfile -t ha-gateway:dev .
docker build -f ai-gateway/Dockerfile -t ai-gateway:dev .
docker build -f discord-bot/Dockerfile -t discord-bot:dev .
gRPC Smoke Checks
With ha-gateway running locally:
grpcurl -plaintext -d '{"domain":"light"}' \
localhost:50051 ha.v1.EntityService/ListStates
grpcurl -plaintext -d '{"entity_id":"light.living_room","brightness_pct":80}' \
localhost:50051 ha.v1.LightService/TurnOn
With ai-gateway running locally:
grpcurl -plaintext -d '{"text":"turn on the desk lamp","source":"local"}' \
localhost:50052 ai.v1.AIService/Query
grpcurl -plaintext -d '{}' localhost:50052 ai.v1.AIService/ListModels
Configuration Notes
LOG_FORMAT=jsonis the production default;LOG_FORMAT=textis easier locally.OTEL_ENDPOINTenables OTLP gRPC traces and metrics. Leave it empty for local no-op telemetry.TLS_DIRenables mTLS. The directory must containtls.crt,tls.key, andca.crt.- Inbound app-layer authorization is not implemented. Keep the gateways on a trusted internal network or use mTLS.