feat: update README.md to enhance project overview and clarify service architecture
This commit is contained in:
parent
7a0b0f1540
commit
d6236d70b9
414
README.md
414
README.md
@ -1,59 +1,276 @@
|
|||||||
# home-service
|
# home-service
|
||||||
|
|
||||||
This workspace contains a Home Assistant gRPC gateway and the protobuf contract
|
This repo is a small Home Assistant control platform built around gRPC.
|
||||||
it serves.
|
|
||||||
|
|
||||||
The current implementation is centered on `ha-gateway`, a Go service that:
|
There are three important pieces:
|
||||||
|
|
||||||
- exposes Home Assistant operations over gRPC
|
- `proto/`: the API contract, written in protobuf
|
||||||
- translates gRPC requests into Home Assistant REST API calls
|
- `gen/`: generated Go code from that contract
|
||||||
- emits OpenTelemetry traces and metrics when configured
|
- `ha-gateway/`: the gRPC server that talks to Home Assistant
|
||||||
- keeps protobuf definitions and generated Go stubs in-repo
|
- `discord-bot/`: a Discord client that talks to `ha-gateway`
|
||||||
|
|
||||||
`EntityService` is implemented, `LightService` supports both discovery and
|
If you are new to gRPC, the most important idea is:
|
||||||
control, `SwitchService` supports discovery, and `EventService` is still
|
|
||||||
scaffolded.
|
|
||||||
|
|
||||||
## Workspace Layout
|
1. define the API once in `.proto` files
|
||||||
|
2. generate client/server code from that definition
|
||||||
|
3. let all services use the same generated types so they agree on request and response shape
|
||||||
|
|
||||||
|
## What Each Folder Does
|
||||||
|
|
||||||
```text
|
```text
|
||||||
.
|
.
|
||||||
├── proto/ # Source protobuf definitions
|
├── proto/ # Source protobuf service and message definitions
|
||||||
├── gen/ # Generated Go protobuf/grpc code (committed)
|
├── gen/ # Generated Go code from proto/
|
||||||
├── ha-gateway/ # Go gRPC server
|
├── ha-gateway/ # gRPC server + Home Assistant REST adapter
|
||||||
|
├── discord-bot/ # Discord slash-command app + gRPC client to ha-gateway
|
||||||
├── buf.yaml # Buf module config
|
├── buf.yaml # Buf module config
|
||||||
├── buf.gen.yaml # Buf codegen config
|
├── buf.gen.yaml # Buf code generation config
|
||||||
└── go.work # Go workspace linking gen + ha-gateway
|
└── go.work # Go workspace linking all local modules
|
||||||
```
|
```
|
||||||
|
|
||||||
## Architecture
|
## Why `gen/` Exists
|
||||||
|
|
||||||
`ha-gateway` follows a ports-and-adapters structure:
|
`gen/` is the bridge between your `.proto` files and your Go services.
|
||||||
|
|
||||||
- `internal/core/domain`: pure domain types
|
The `.proto` files in `proto/ha/v1/` are the source of truth. They define:
|
||||||
- `internal/core/ports/driving`: interfaces exposed to primary adapters
|
|
||||||
- `internal/core/ports/driven`: interfaces the app layer depends on
|
|
||||||
- `internal/app`: application logic for entity, light, and switch operations
|
|
||||||
- `internal/adapters/primary/grpc`: gRPC handlers and proto/domain mapping
|
|
||||||
- `internal/adapters/secondary/ha`: Home Assistant REST client
|
|
||||||
- `internal/telemetry`: OpenTelemetry setup
|
|
||||||
|
|
||||||
The runtime flow is:
|
- service names like `LightService` and `SwitchService`
|
||||||
|
- RPC methods like `ListLights`, `TurnOn`, and `ListSwitches`
|
||||||
|
- message schemas like `TurnOnRequest`, `LightEntity`, and `SwitchEntity`
|
||||||
|
|
||||||
1. A gRPC client calls `EntityService`, `LightService`, or `SwitchService`.
|
Those `.proto` files are not directly used by Go at runtime. They are compiled
|
||||||
2. The gRPC adapter maps protobuf messages into domain parameters.
|
into Go source files in `gen/ha/v1/`, such as:
|
||||||
3. The app layer orchestrates the use case.
|
|
||||||
4. The HA adapter calls Home Assistant's REST API.
|
|
||||||
5. The response is mapped back into the protobuf response.
|
|
||||||
|
|
||||||
For discovery-style RPCs, the light and switch apps cache filtered entity lists
|
- `light.pb.go`
|
||||||
from Home Assistant state snapshots. The cache is primed at startup on a
|
- `light_grpc.pb.go`
|
||||||
best-effort basis and lazily refreshed on the first request if startup
|
- `switch.pb.go`
|
||||||
discovery fails.
|
- `switch_grpc.pb.go`
|
||||||
|
|
||||||
## Services
|
That generated code gives you:
|
||||||
|
|
||||||
### Implemented
|
- Go structs for protobuf messages
|
||||||
|
- gRPC client interfaces for callers
|
||||||
|
- gRPC server interfaces and registration helpers for servers
|
||||||
|
|
||||||
|
In this repo:
|
||||||
|
|
||||||
|
- `discord-bot` imports `gitea.nik4nao.com/nik/home-services/gen/ha/v1` to get
|
||||||
|
generated gRPC clients like `hav1.LightServiceClient`
|
||||||
|
- `ha-gateway` imports the same package to register generated gRPC servers like
|
||||||
|
`hav1.RegisterLightServiceServer(...)`
|
||||||
|
|
||||||
|
Without `gen/`, both services would need to hand-write and manually keep in
|
||||||
|
sync:
|
||||||
|
|
||||||
|
- request/response structs
|
||||||
|
- method names
|
||||||
|
- serialization logic
|
||||||
|
- client/server glue
|
||||||
|
|
||||||
|
That is exactly what gRPC code generation is meant to remove.
|
||||||
|
|
||||||
|
## High-Level Data Flow
|
||||||
|
|
||||||
|
The request flow for a Discord command looks like this:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Discord user
|
||||||
|
-> discord-bot primary adapter
|
||||||
|
-> discord-bot app layer
|
||||||
|
-> discord-bot gRPC client adapter
|
||||||
|
-> generated gRPC client code from gen/
|
||||||
|
-> network
|
||||||
|
-> generated gRPC server code from gen/
|
||||||
|
-> ha-gateway gRPC adapter
|
||||||
|
-> ha-gateway app layer
|
||||||
|
-> ha-gateway Home Assistant REST adapter
|
||||||
|
-> Home Assistant
|
||||||
|
```
|
||||||
|
|
||||||
|
And then the response goes back in reverse.
|
||||||
|
|
||||||
|
## Concrete Example: `/light on`
|
||||||
|
|
||||||
|
Here is the real request path in this repo when a user runs `/light on` in
|
||||||
|
Discord.
|
||||||
|
|
||||||
|
### 1. Discord receives the slash command
|
||||||
|
|
||||||
|
`discord-bot` opens a Discord session in
|
||||||
|
[main.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/cmd/bot/main.go)
|
||||||
|
and registers a handler from
|
||||||
|
[handler.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/internal/adapters/primary/discord/handler.go).
|
||||||
|
|
||||||
|
When the user runs:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/light on light:light.desk brightness:80 color_temp:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
Discord sends an interaction event to the bot.
|
||||||
|
|
||||||
|
### 2. The Discord adapter routes the command
|
||||||
|
|
||||||
|
In
|
||||||
|
[handler.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/internal/adapters/primary/discord/handler.go),
|
||||||
|
the command is routed by command name and subcommand:
|
||||||
|
|
||||||
|
- `light.on` goes to `HandleLightOn(...)`
|
||||||
|
|
||||||
|
This is still Discord-specific code. It knows about slash-command options and
|
||||||
|
ephemeral responses.
|
||||||
|
|
||||||
|
### 3. The app layer turns the command into an internal use case
|
||||||
|
|
||||||
|
In
|
||||||
|
[command.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/internal/app/command.go),
|
||||||
|
`HandleLightOn(...)` does two things:
|
||||||
|
|
||||||
|
- looks up a friendly light name for the confirmation message
|
||||||
|
- calls the driven port `TurnOnLight(...)`
|
||||||
|
|
||||||
|
This layer does not know protobuf details. It only knows the app wants to turn
|
||||||
|
on a light.
|
||||||
|
|
||||||
|
### 4. The secondary adapter turns that use case into a gRPC request
|
||||||
|
|
||||||
|
In
|
||||||
|
[client.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/internal/adapters/secondary/gateway/client.go),
|
||||||
|
`TurnOnLight(...)` creates:
|
||||||
|
|
||||||
|
- a generated protobuf request: `hav1.TurnOnRequest`
|
||||||
|
- and sends it with a generated gRPC client: `hav1.LightServiceClient`
|
||||||
|
|
||||||
|
This is the exact place where `discord-bot` depends on `gen/`.
|
||||||
|
|
||||||
|
Why?
|
||||||
|
|
||||||
|
Because `hav1.TurnOnRequest` and `hav1.LightServiceClient` are generated from
|
||||||
|
`proto/ha/v1/light.proto`.
|
||||||
|
|
||||||
|
### 5. gRPC sends the protobuf message over the network
|
||||||
|
|
||||||
|
The generated client serializes the request into protobuf bytes and sends it to
|
||||||
|
`ha-gateway` over gRPC.
|
||||||
|
|
||||||
|
At this point:
|
||||||
|
|
||||||
|
- `discord-bot` does not know anything about Home Assistant REST
|
||||||
|
- it only knows the gRPC contract defined in `proto/`
|
||||||
|
|
||||||
|
### 6. `ha-gateway` receives the RPC
|
||||||
|
|
||||||
|
In
|
||||||
|
[main.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ha-gateway/cmd/gateway/main.go),
|
||||||
|
`ha-gateway` registers the generated server bindings:
|
||||||
|
|
||||||
|
- `hav1.RegisterLightServiceServer(...)`
|
||||||
|
- `hav1.RegisterSwitchServiceServer(...)`
|
||||||
|
- `hav1.RegisterEntityServiceServer(...)`
|
||||||
|
|
||||||
|
The generated gRPC server code from `gen/` receives the network request and
|
||||||
|
dispatches it to the real handler implementation in
|
||||||
|
[light.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ha-gateway/internal/adapters/primary/grpc/light.go).
|
||||||
|
|
||||||
|
This is the exact mirror image of the client side:
|
||||||
|
|
||||||
|
- `discord-bot` uses generated client code
|
||||||
|
- `ha-gateway` uses generated server code
|
||||||
|
|
||||||
|
### 7. The gRPC adapter maps protobuf types into domain input
|
||||||
|
|
||||||
|
In
|
||||||
|
[light.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ha-gateway/internal/adapters/primary/grpc/light.go),
|
||||||
|
the handler receives `*hav1.TurnOnRequest`.
|
||||||
|
|
||||||
|
It converts that protobuf message into domain parameters and calls the app
|
||||||
|
service.
|
||||||
|
|
||||||
|
This separation matters because it keeps the core app logic from depending on
|
||||||
|
protobuf or transport-specific concerns.
|
||||||
|
|
||||||
|
### 8. The app layer decides what Home Assistant call to make
|
||||||
|
|
||||||
|
In `ha-gateway/internal/app/light.go`, the app layer builds a service payload
|
||||||
|
such as:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"entity_id": "light.desk",
|
||||||
|
"brightness_pct": 80,
|
||||||
|
"color_temp_kelvin": 3000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then it calls the driven Home Assistant client.
|
||||||
|
|
||||||
|
### 9. The Home Assistant adapter performs the REST call
|
||||||
|
|
||||||
|
In
|
||||||
|
[client.go](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ha-gateway/internal/adapters/secondary/ha/client.go),
|
||||||
|
`CallService(...)` sends an HTTP request to Home Assistant:
|
||||||
|
|
||||||
|
- `POST /api/services/light/turn_on`
|
||||||
|
|
||||||
|
using the Home Assistant base URL and token from env config.
|
||||||
|
|
||||||
|
### 10. The response comes back up the stack
|
||||||
|
|
||||||
|
Then the flow reverses:
|
||||||
|
|
||||||
|
1. Home Assistant returns JSON
|
||||||
|
2. `ha-gateway` maps it into internal state
|
||||||
|
3. `ha-gateway` maps internal state into generated protobuf response types
|
||||||
|
4. generated gRPC server code serializes the response
|
||||||
|
5. generated gRPC client code in `discord-bot` deserializes it
|
||||||
|
6. `discord-bot` app layer formats a human response like:
|
||||||
|
`Turned on 'Desk Lamp' (brightness 80%, 3000K).`
|
||||||
|
7. the Discord adapter sends that message back to Discord
|
||||||
|
|
||||||
|
## Why This Is Split Into Multiple Layers
|
||||||
|
|
||||||
|
If you are new to gRPC architecture, it can feel like there are too many steps.
|
||||||
|
Each layer has a specific job:
|
||||||
|
|
||||||
|
- `proto/`: defines the API contract
|
||||||
|
- `gen/`: generated transport code from the contract
|
||||||
|
- `discord-bot` primary adapter: understands Discord interactions
|
||||||
|
- `discord-bot` app layer: understands command behavior
|
||||||
|
- `discord-bot` secondary adapter: understands how to call `ha-gateway`
|
||||||
|
- `ha-gateway` primary adapter: understands incoming gRPC requests
|
||||||
|
- `ha-gateway` app layer: understands home-control use cases
|
||||||
|
- `ha-gateway` secondary adapter: understands Home Assistant REST
|
||||||
|
|
||||||
|
This gives you clean boundaries:
|
||||||
|
|
||||||
|
- change Discord UX without changing Home Assistant integration
|
||||||
|
- change Home Assistant REST details without changing Discord commands
|
||||||
|
- add another client later, like CLI or Alexa, using the same gRPC contract
|
||||||
|
|
||||||
|
## `proto/` vs `gen/` in Simple Terms
|
||||||
|
|
||||||
|
Think of it like this:
|
||||||
|
|
||||||
|
- `proto/` is the design
|
||||||
|
- `gen/` is the compiled implementation of that design for Go
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
- `proto/ha/v1/light.proto` says there is a `LightService` with `TurnOn`
|
||||||
|
- `gen/ha/v1/light_grpc.pb.go` generates the Go client/server plumbing
|
||||||
|
- `gen/ha/v1/light.pb.go` generates the Go message structs
|
||||||
|
|
||||||
|
Both services use the same generated package:
|
||||||
|
|
||||||
|
- same method names
|
||||||
|
- same fields
|
||||||
|
- same wire format
|
||||||
|
|
||||||
|
That is what keeps both sides compatible.
|
||||||
|
|
||||||
|
## Current Service Status
|
||||||
|
|
||||||
|
### Implemented in `ha-gateway`
|
||||||
|
|
||||||
- `ha.v1.EntityService`
|
- `ha.v1.EntityService`
|
||||||
- `GetState`
|
- `GetState`
|
||||||
@ -66,45 +283,56 @@ discovery fails.
|
|||||||
- `ha.v1.SwitchService`
|
- `ha.v1.SwitchService`
|
||||||
- `ListSwitches`
|
- `ListSwitches`
|
||||||
|
|
||||||
### Partially Stubbed
|
### Partially Stubbed in `ha-gateway`
|
||||||
|
|
||||||
- `ha.v1.SwitchService`
|
- `ha.v1.SwitchService`
|
||||||
- `TurnOn`
|
- `TurnOn`
|
||||||
- `TurnOff`
|
- `TurnOff`
|
||||||
- `Toggle`
|
- `Toggle`
|
||||||
|
|
||||||
### Stubbed
|
### Stubbed in `ha-gateway`
|
||||||
|
|
||||||
- `ha.v1.EventService`
|
- `ha.v1.EventService`
|
||||||
|
|
||||||
The event path is planned around Home Assistant WebSocket subscriptions, but the
|
## Workspace Setup
|
||||||
WebSocket adapter and fan-out broker are not implemented yet.
|
|
||||||
|
This repo uses a Go workspace:
|
||||||
|
|
||||||
|
```text
|
||||||
|
go.work
|
||||||
|
-> ./gen
|
||||||
|
-> ./ha-gateway
|
||||||
|
-> ./discord-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
That lets local modules import each other without publishing intermediate
|
||||||
|
versions while developing.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
`ha-gateway` reads configuration from environment variables. A sample file lives
|
### `ha-gateway`
|
||||||
at [ha-gateway/.env.example](/Users/nik-macbookair/repo/home-service/ha-gateway/.env.example).
|
|
||||||
|
Sample env file:
|
||||||
|
[ha-gateway/.env.example](https://gitea.nik4nao.com/nik/home-services/src/branch/main/ha-gateway/.env.example)
|
||||||
|
|
||||||
| Variable | Required | Default | Notes |
|
| Variable | Required | Default | Notes |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `HA_TOKEN` | yes | none | Home Assistant long-lived access token |
|
| `HA_TOKEN` | yes | none | Home Assistant long-lived access token |
|
||||||
| `GRPC_PORT` | no | `50051` | gRPC listen port |
|
| `GRPC_PORT` | no | `50051` | gRPC listen port |
|
||||||
| `HA_BASE_URL` | effectively yes | empty | Example: `http://ha.home.arpa:8123` |
|
| `HA_BASE_URL` | effectively yes | empty | Example: `http://ha.home.arpa:8123` |
|
||||||
| `OTEL_ENDPOINT` | no | empty | OTLP gRPC endpoint; empty disables telemetry |
|
| `OTEL_ENDPOINT` | no | empty | OTLP gRPC endpoint |
|
||||||
|
|
||||||
Notes:
|
### `discord-bot`
|
||||||
|
|
||||||
- startup fails if `HA_TOKEN` is missing
|
Sample env file:
|
||||||
- `HA_BASE_URL` is not validated on load, but the gateway cannot reach Home
|
[discord-bot/.env.example](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/.env.example)
|
||||||
Assistant without it
|
|
||||||
- if `OTEL_ENDPOINT` is empty, the service installs no-op telemetry providers
|
|
||||||
|
|
||||||
## Prerequisites
|
| Variable | Required | Notes |
|
||||||
|
| --- | --- | --- |
|
||||||
- Go `1.26`
|
| `DISCORD_TOKEN` | yes | Discord bot token |
|
||||||
- `buf` for protobuf generation
|
| `GUILD_ID` | no | Guild command registration target |
|
||||||
- a reachable Home Assistant instance
|
| `HA_GATEWAY_ADDR` | yes | gRPC address of `ha-gateway` |
|
||||||
- a valid Home Assistant long-lived access token
|
| `OTEL_ENDPOINT` | no | OTLP gRPC endpoint |
|
||||||
|
|
||||||
## Generate Protobuf Code
|
## Generate Protobuf Code
|
||||||
|
|
||||||
@ -114,70 +342,57 @@ Run from the repo root:
|
|||||||
buf generate
|
buf generate
|
||||||
```
|
```
|
||||||
|
|
||||||
Generated files are written to `gen/ha/v1`.
|
That regenerates `gen/ha/v1/*.pb.go` from `proto/ha/v1/*.proto`.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
Sync the workspace, then build the gateway:
|
Build each module from its own directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go work sync
|
cd gen && go build ./...
|
||||||
cd ha-gateway
|
cd ../ha-gateway && go build ./...
|
||||||
go build ./...
|
cd ../discord-bot && go build ./...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run Locally
|
## Run Locally
|
||||||
|
|
||||||
Create a local env file:
|
### Start `ha-gateway`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cp ha-gateway/.env.example ha-gateway/.env
|
cp ha-gateway/.env.example ha-gateway/.env
|
||||||
```
|
|
||||||
|
|
||||||
Fill in `HA_TOKEN` and `HA_BASE_URL`, then start the server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ha-gateway
|
cd ha-gateway
|
||||||
go run ./cmd/gateway
|
go run ./cmd/gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
The gateway listens on `:50051` by default.
|
### Start `discord-bot`
|
||||||
|
|
||||||
## Smoke Test With grpcurl
|
```bash
|
||||||
|
cp discord-bot/.env.example discord-bot/.env
|
||||||
|
cd discord-bot
|
||||||
|
go run ./cmd/bot
|
||||||
|
```
|
||||||
|
|
||||||
The server registers gRPC reflection, so `grpcurl` can inspect it directly:
|
## Smoke Test `ha-gateway`
|
||||||
|
|
||||||
|
Because `ha-gateway` registers gRPC reflection, you can inspect it with
|
||||||
|
`grpcurl`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
grpcurl -plaintext localhost:50051 list
|
grpcurl -plaintext localhost:50051 list
|
||||||
grpcurl -plaintext localhost:50051 describe ha.v1.LightService
|
grpcurl -plaintext localhost:50051 describe ha.v1.LightService
|
||||||
```
|
```
|
||||||
|
|
||||||
Examples against a locally running gateway:
|
Examples:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# List states filtered by domain
|
|
||||||
grpcurl -plaintext -d '{"domain":"light"}' \
|
|
||||||
localhost:50051 ha.v1.EntityService/ListStates
|
|
||||||
|
|
||||||
# List discovered lights
|
|
||||||
grpcurl -plaintext -d '{}' \
|
grpcurl -plaintext -d '{}' \
|
||||||
localhost:50051 ha.v1.LightService/ListLights
|
localhost:50051 ha.v1.LightService/ListLights
|
||||||
|
|
||||||
# List discovered switches
|
|
||||||
grpcurl -plaintext -d '{}' \
|
|
||||||
localhost:50051 ha.v1.SwitchService/ListSwitches
|
|
||||||
|
|
||||||
# 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}' \
|
grpcurl -plaintext -d '{"entity_id":"light.living_room","brightness_pct":80}' \
|
||||||
localhost:50051 ha.v1.LightService/TurnOn
|
localhost:50051 ha.v1.LightService/TurnOn
|
||||||
|
|
||||||
# Toggle a light
|
grpcurl -plaintext -d '{}' \
|
||||||
grpcurl -plaintext -d '{"entity_id":"light.living_room"}' \
|
localhost:50051 ha.v1.SwitchService/ListSwitches
|
||||||
localhost:50051 ha.v1.LightService/Toggle
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
@ -186,31 +401,22 @@ Build from the repo root:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -f ha-gateway/Dockerfile -t ha-gateway:dev .
|
docker build -f ha-gateway/Dockerfile -t ha-gateway:dev .
|
||||||
```
|
docker build -f discord-bot/Dockerfile -t discord-bot:dev .
|
||||||
|
|
||||||
Run it with the same env file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --env-file ha-gateway/.env -p 50051:50051 ha-gateway:dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Telemetry
|
## Telemetry
|
||||||
|
|
||||||
When `OTEL_ENDPOINT` is set, the gateway exports:
|
Both runtime services support OTLP/gRPC telemetry:
|
||||||
|
|
||||||
- traces via OTLP/gRPC
|
- `ha-gateway` uses service name `ha-gateway`
|
||||||
- metrics via OTLP/gRPC
|
- `discord-bot` uses service name `discord-bot`
|
||||||
|
|
||||||
The service name is `ha-gateway`. When `OTEL_ENDPOINT` is unset, telemetry is
|
If `OTEL_ENDPOINT` is empty, telemetry is disabled.
|
||||||
disabled for local development.
|
|
||||||
|
|
||||||
## Current Limitations
|
## Current Limitations
|
||||||
|
|
||||||
- no authentication/authorization on inbound gRPC requests yet
|
- no auth on inbound gRPC requests yet
|
||||||
- `SwitchService` control RPCs (`TurnOn`, `TurnOff`, `Toggle`) still return
|
- `SwitchService` control RPCs are still unimplemented
|
||||||
`Unimplemented`
|
- `EventService` is still unimplemented
|
||||||
- `EventService` is not implemented
|
|
||||||
- Home Assistant event streaming over WebSocket is not implemented
|
- Home Assistant event streaming over WebSocket is not implemented
|
||||||
- there are currently no unit tests in the repo
|
- there are currently no unit tests in the repo
|
||||||
|
|
||||||
The auth note in [ha-gateway/cmd/gateway/main.go](/Users/nik-macbookair/repo/home-service/ha-gateway/cmd/gateway/main.go) explicitly calls out API-key and mTLS as future options before exposing the gateway outside a trusted network.
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user