Nik Afiq 8f7024edfa
All checks were successful
CI / changes (push) Successful in 19s
CI / test (push) Successful in 24s
CI / build-ai-gateway (push) Successful in 1m6s
CI / build-ha-gateway (push) Successful in 1m3s
CI / build-discord-bot (push) Successful in 1m4s
CI / build-alexa-bridge (push) Successful in 1m15s
CI / build-tts-gateway (push) Successful in 1m5s
CI / build-tts-sidecar (push) Has been skipped
CI / build-tts-model (push) Has been skipped
feat(climate): add SetTemperature method to ClimateService
- Implemented SetTemperature in ClimateService for setting an absolute target temperature.
- Updated ClimateServiceClient and ClimateServiceServer interfaces to include SetTemperature.
- Added corresponding handler and tests for SetTemperature in ClimateGRPC.
- Modified ClimateApp to handle SetTemperature requests without clamping.
- Updated climate.proto to define SetTemperatureRequest message.
- Adjusted Dockerfiles to include alexa-bridge dependencies.
2026-07-25 12:08:24 +09:00

128 lines
4.1 KiB
Go

package haclient
import (
"context"
"fmt"
"strings"
hav1 "gitea.nik4nao.com/nik/home-services/gen/ha/v1"
)
// ExecuteAction implements driven.Controller. It dispatches by entity domain
// (the entity_id prefix up to the first '.') to the matching ha-gateway
// service, then by action within that domain. See alexa-bridge/plan.md's
// action table for the full (domain, action) -> RPC mapping.
func (c *Client) ExecuteAction(ctx context.Context, entityID, action string, params map[string]any) error {
domain, _, ok := strings.Cut(entityID, ".")
if !ok {
return fmt.Errorf("entity id %q has no domain prefix", entityID)
}
switch domain {
case "light":
return c.executeLightAction(ctx, entityID, action, params)
case "switch":
return c.executeSwitchAction(ctx, entityID, action, params)
case "climate":
return c.executeClimateAction(ctx, entityID, action, params)
default:
return fmt.Errorf("unsupported entity domain %q for entity %q", domain, entityID)
}
}
func (c *Client) executeLightAction(ctx context.Context, entityID, action string, params map[string]any) error {
switch action {
case "turn_on":
_, err := c.lightClient.TurnOn(ctx, &hav1.TurnOnRequest{
EntityId: entityID,
BrightnessPct: optUint32(params, "brightness_pct"),
ColorTempKelvin: optUint32(params, "color_temp_kelvin"),
RgbColor: optRGB(params, "rgb_color"),
Transition: optUint32(params, "transition"),
})
return err
case "turn_off":
_, err := c.lightClient.TurnOff(ctx, &hav1.TurnOffRequest{
EntityId: entityID,
Transition: optUint32(params, "transition"),
})
return err
case "toggle":
_, err := c.lightClient.Toggle(ctx, &hav1.ToggleRequest{EntityId: entityID})
return err
case "set_brightness":
brightness, err := reqUint32(params, "brightness_pct")
if err != nil {
return err
}
_, err = c.lightClient.TurnOn(ctx, &hav1.TurnOnRequest{EntityId: entityID, BrightnessPct: &brightness})
return err
case "set_color_temp":
colorTemp, err := reqUint32(params, "color_temp_kelvin")
if err != nil {
return err
}
_, err = c.lightClient.TurnOn(ctx, &hav1.TurnOnRequest{EntityId: entityID, ColorTempKelvin: &colorTemp})
return err
case "set_color":
rgb, err := reqRGB(params, "rgb_color")
if err != nil {
return err
}
_, err = c.lightClient.TurnOn(ctx, &hav1.TurnOnRequest{EntityId: entityID, RgbColor: rgb})
return err
default:
return fmt.Errorf("unsupported light action %q", action)
}
}
func (c *Client) executeSwitchAction(ctx context.Context, entityID, action string, _ map[string]any) error {
req := &hav1.SwitchRequest{EntityId: entityID}
switch action {
case "turn_on":
_, err := c.switchClient.TurnOn(ctx, req)
return err
case "turn_off":
_, err := c.switchClient.TurnOff(ctx, req)
return err
case "toggle":
_, err := c.switchClient.Toggle(ctx, req)
return err
default:
return fmt.Errorf("unsupported switch action %q", action)
}
}
func (c *Client) executeClimateAction(ctx context.Context, entityID, action string, params map[string]any) error {
switch action {
case "turn_on":
_, err := c.climateClient.TurnOn(ctx, &hav1.ClimateRequest{EntityId: entityID})
return err
case "turn_off":
_, err := c.climateClient.TurnOff(ctx, &hav1.ClimateRequest{EntityId: entityID})
return err
case "set_hvac_mode":
mode, err := reqString(params, "hvac_mode")
if err != nil {
return err
}
_, err = c.climateClient.SetHVACMode(ctx, &hav1.SetHVACModeRequest{EntityId: entityID, HvacMode: mode})
return err
case "increase_temperature":
_, err := c.climateClient.IncreaseTemperature(ctx, &hav1.ClimateRequest{EntityId: entityID})
return err
case "decrease_temperature":
_, err := c.climateClient.DecreaseTemperature(ctx, &hav1.ClimateRequest{EntityId: entityID})
return err
case "set_temperature":
target, err := reqFloat64(params, "target_temperature")
if err != nil {
return err
}
_, err = c.climateClient.SetTemperature(ctx, &hav1.SetTemperatureRequest{EntityId: entityID, TargetTemperature: target})
return err
default:
return fmt.Errorf("unsupported climate action %q", action)
}
}