All checks were successful
CI / changes (push) Successful in 19s
CI / test (push) Successful in 31s
CI / build-ai-gateway (push) Successful in 1m8s
CI / build-ha-gateway (push) Successful in 1m19s
CI / build-discord-bot (push) Successful in 59s
CI / build-alexa-bridge (push) Successful in 1m8s
CI / build-alert-bridge (push) Successful in 1m17s
CI / build-tts-gateway (push) Successful in 1m10s
CI / build-tts-sidecar (push) Has been skipped
CI / build-tts-model (push) Has been skipped
New standalone service that receives authenticated HTTP POSTs (e.g. from a cronjob elsewhere on the home network) and posts them to a Discord channel via an Incoming Webhook. Fire-and-forget, no dependency on discord-bot's bot session at all - mirrors alexa-bridge's precedent of a small bridge service with its own HTTP listener and auth rather than adding an inbound edge to an existing internal service. Wires alert-bridge into go.work, CI (changes filter, test job, new build-alert-bridge job), and the other five Dockerfiles' COPY lines. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ha-gateway
ha-gateway is the internal gRPC boundary for Home Assistant. It exposes a
small protobuf API to other home services and keeps Home Assistant tokens and
REST details out of clients.
Runtime Flow
- The service loads
.env, configures logging and telemetry, and starts gRPC onGRPC_PORT. - App services are wired to a Home Assistant REST adapter and, when
SWITCHBOT_TOKEN/SWITCHBOT_SECRETare set, a SwitchBot Cloud adapter. - Light, switch, and climate discovery caches are refreshed during startup when possible.
- gRPC clients call entity, light, switch, climate, remote, or event services.
- The adapter maps requests to Home Assistant REST state/service calls, or
for
RemoteService, signed SwitchBot Cloud Open API requests.
gRPC API
Contracts are defined under proto/ha/v1.
Implemented:
EntityService.GetStateEntityService.ListStatesLightService.TurnOnLightService.TurnOffLightService.ToggleLightService.ListLightsSwitchService.TurnOnSwitchService.TurnOffSwitchService.ToggleSwitchService.ListSwitchesClimateService.TurnOnClimateService.TurnOffClimateService.IncreaseTemperatureClimateService.DecreaseTemperatureClimateService.SetHVACModeClimateService.ListClimatesRemoteService.SendCommand
Stubbed:
EventService
The server also registers gRPC health checks and reflection.
Configuration
Environment variables:
| Variable | Default | Description |
|---|---|---|
GRPC_PORT |
50051 |
gRPC listen port |
HA_BASE_URL |
empty | Home Assistant base URL, for example http://ha.home.arpa:8123 |
HA_TOKEN |
required | Home Assistant long-lived access token |
TLS_DIR |
empty | Enables mTLS for the gRPC server when set |
OTEL_ENDPOINT |
empty | OTLP gRPC collector endpoint; empty disables telemetry |
LOG_LEVEL |
info |
debug, info, warn, or error |
LOG_FORMAT |
json |
json or text |
SWITCHBOT_TOKEN |
empty | optional; enables SwitchBot Cloud custom IR commands |
SWITCHBOT_SECRET |
empty | optional; enables SwitchBot Cloud custom IR commands |
Example env file: .env.example
When TLS_DIR is set, the directory must contain tls.crt, tls.key, and
ca.crt.
Local Run
cp .env.example .env
go run ./cmd/gateway
Run from ha-gateway/ so godotenv loads ha-gateway/.env.
For local plaintext development:
GRPC_PORT=50051
HA_BASE_URL=http://ha.home.arpa:8123
HA_TOKEN=<long-lived-token>
TLS_DIR=
Smoke Checks
grpcurl -plaintext -d '{"domain":"light"}' \
localhost:50051 ha.v1.EntityService/ListStates
grpcurl -plaintext -d '{}' localhost:50051 ha.v1.LightService/ListLights
grpcurl -plaintext -d '{"entity_id":"light.living_room","brightness_pct":80}' \
localhost:50051 ha.v1.LightService/TurnOn
grpcurl -plaintext -d '{}' localhost:50051 ha.v1.ClimateService/ListClimates
grpcurl -plaintext -d '{}' localhost:50051 grpc.health.v1.Health/Check
Test And Build
go test ./...
go build ./...
Build the container image from the workspace root:
docker build -f ha-gateway/Dockerfile -t ha-gateway:dev .
Optionally pass a build version:
docker build -f ha-gateway/Dockerfile --build-arg VERSION=$(git rev-parse --short HEAD) -t ha-gateway:dev .
Package Map
cmd/gateway/ # process entrypoint and wiring
internal/adapters/primary/grpc/ # gRPC service implementations
internal/adapters/secondary/ha/ # Home Assistant REST adapter
internal/adapters/secondary/switchbot/ # SwitchBot Cloud Open API adapter
internal/app/ # entity, light, switch, climate, and remote orchestration
internal/config/ # environment loading
internal/core/domain/ # domain types
internal/core/ports/ # driving and driven interfaces
internal/logger/ # slog setup
internal/telemetry/ # OpenTelemetry setup
Limitations
EventServiceis registered but not implemented.- Home Assistant WebSocket event streaming is still a TODO.
- Keep this service internal or protect it with mTLS; it does not implement separate app-layer authorization.