- Added ClimateApp to handle climate entity operations including turning on/off, adjusting temperature, and setting HVAC modes. - Implemented caching mechanism for climate entities to optimize state retrieval. - Created domain model for Climate with attributes such as current temperature, target temperature, and HVAC modes. - Developed unit tests for ClimateApp to ensure functionality and correctness. feat: add RemoteApp for SwitchBot commands - Introduced RemoteApp to facilitate sending commands to SwitchBot devices. - Implemented SendCommand method for executing device commands without state management. chore: update configuration for SwitchBot integration - Added SwitchBotToken and SwitchBotSecret to configuration for enabling SwitchBot Cloud commands. feat: define gRPC services for Climate and Remote operations - Created climate.proto and remote.proto files to define gRPC services for climate management and remote command execution. - Implemented corresponding request and response message structures for gRPC interactions.
150 lines
4.5 KiB
Markdown
150 lines
4.5 KiB
Markdown
# discord-bot
|
|
|
|
`discord-bot` is a Discord slash-command service for home control. It calls
|
|
`ha-gateway` for direct Home Assistant actions and `ai-gateway` for free-form
|
|
AI-assisted commands.
|
|
|
|
## Runtime Flow
|
|
|
|
1. The process loads `.env`, opens a Discord session, and registers slash
|
|
commands.
|
|
2. A user runs a command such as `/light list`, `/light on`, or `/ai query`.
|
|
3. The Discord adapter validates and routes the interaction to the app layer.
|
|
4. The app layer calls `ha-gateway` or `ai-gateway` through secondary gRPC
|
|
adapters.
|
|
5. The bot sends a Discord response. Long-running AI work is tracked so
|
|
shutdown can wait briefly for in-flight requests.
|
|
|
|
## Commands
|
|
|
|
### Lights
|
|
|
|
```text
|
|
/light list
|
|
/light on light:<entity> brightness:80 color_temp:3000
|
|
/light off light:<entity> transition:3
|
|
/light toggle light:<entity>
|
|
```
|
|
|
|
- `light` is required for action commands and uses autocomplete.
|
|
- `brightness` is optional and accepts `1-100`.
|
|
- `color_temp` is optional and accepts `2000-6535` kelvin.
|
|
- `transition` is optional and accepts `0-30` seconds.
|
|
|
|
### Switches
|
|
|
|
```text
|
|
/switch list
|
|
/switch on switch:<entity>
|
|
/switch off switch:<entity>
|
|
/switch toggle switch:<entity>
|
|
```
|
|
|
|
- `switch` is required for action commands and uses autocomplete.
|
|
|
|
### Air Conditioner
|
|
|
|
```text
|
|
/ac on ac:<entity>
|
|
/ac off ac:<entity>
|
|
/ac mode ac:<entity> mode:<Cool|Heat|Dry|Auto|Fan>
|
|
/ac temp up ac:<entity>
|
|
/ac temp down ac:<entity>
|
|
```
|
|
|
|
- `ac` is required for every subcommand and uses autocomplete.
|
|
- `mode` is a fixed choice list mapping to Home Assistant HVAC modes
|
|
(Cool→`cool`, Heat→`heat`, Dry→`dry`, Auto→`heat_cool`, Fan→`fan_only`).
|
|
- `temp up`/`temp down` step the target temperature by one
|
|
`target_temp_step` increment, clamped to the entity's `min_temp`/`max_temp`.
|
|
|
|
### AI
|
|
|
|
```text
|
|
/ai query text:<prompt>
|
|
/ai model list
|
|
/ai model get
|
|
/ai model set name:<model>
|
|
```
|
|
|
|
AI queries are sent to `ai-gateway`. The active model is stored in process
|
|
memory, so it resets when the bot restarts.
|
|
|
|
## Configuration
|
|
|
|
Environment variables:
|
|
|
|
| Variable | Default | Description |
|
|
| --- | --- | --- |
|
|
| `DISCORD_TOKEN` | required | Discord bot token |
|
|
| `GUILD_ID` | empty | Guild-scoped command registration target; empty registers global commands |
|
|
| `HA_GATEWAY_ADDR` | required | gRPC address for `ha-gateway` |
|
|
| `AI_GATEWAY_ADDR` | `ai-gateway.home-services.svc.cluster.local:50052` | gRPC address for `ai-gateway` |
|
|
| `TLS_DIR` | empty | Enables mTLS for gateway clients 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` |
|
|
|
|
Example env file: [.env.example](https://gitea.nik4nao.com/nik/home-services/src/branch/main/discord-bot/.env.example)
|
|
|
|
When `TLS_DIR` is set, the directory must contain `tls.crt`, `tls.key`, and
|
|
`ca.crt`.
|
|
|
|
## Local Run
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
go run ./cmd/bot
|
|
```
|
|
|
|
Run from `discord-bot/` so `godotenv` loads `discord-bot/.env`.
|
|
|
|
For local plaintext gateway connections, leave `TLS_DIR` empty and use:
|
|
|
|
```text
|
|
HA_GATEWAY_ADDR=localhost:50051
|
|
AI_GATEWAY_ADDR=localhost:50052
|
|
```
|
|
|
|
## Test And Build
|
|
|
|
```bash
|
|
go test ./...
|
|
go build ./...
|
|
```
|
|
|
|
Build the container image from the workspace root:
|
|
|
|
```bash
|
|
docker build -f discord-bot/Dockerfile -t discord-bot:dev .
|
|
```
|
|
|
|
Optionally pass a build version:
|
|
|
|
```bash
|
|
docker build -f discord-bot/Dockerfile --build-arg VERSION=$(git rev-parse --short HEAD) -t discord-bot:dev .
|
|
```
|
|
|
|
## Package Map
|
|
|
|
```text
|
|
cmd/bot/ # process entrypoint and wiring
|
|
internal/adapters/primary/discord/ # slash command registration and handlers
|
|
internal/adapters/secondary/gateway/ # ha-gateway gRPC client
|
|
internal/adapters/secondary/aigateway/ # ai-gateway gRPC client
|
|
internal/app/ # command orchestration and formatting
|
|
internal/config/ # environment loading
|
|
internal/core/ports/driven/ # app-facing gateway interfaces
|
|
internal/modelstore/ # in-memory active AI model store
|
|
internal/modelvalidator/ # model availability checks
|
|
internal/logger/ # slog setup
|
|
internal/telemetry/ # OpenTelemetry setup
|
|
```
|
|
|
|
## Limitations
|
|
|
|
- The active AI model is not persisted.
|
|
- The bot relies on Discord auth plus internal gateway/network controls; it
|
|
does not implement per-user authorization.
|
|
- List output is optimized for monospace Discord messages, not rich embeds.
|