Nik Afiq 6ea4e84949
All checks were successful
CI / test (push) Successful in 4s
CI / build-ha-gateway (push) Successful in 1m7s
CI / build-discord-bot (push) Successful in 51s
Enhance Discord bot and HA gateway with improved structure and documentation
- Added detailed comments to clarify the purpose of various functions and types in the Discord bot and HA gateway.
- Introduced new methods in the CommandApp for handling light and switch operations, including HandleLightOn, HandleLightOff, HandleLightToggle, and their respective autocomplete functions.
- Updated the HAClient interface to include methods for fetching states and calling services, enhancing the interaction with Home Assistant.
- Improved the structure of entity and light domain models to include additional attributes and clearer documentation.
- Implemented logging enhancements in both the Discord bot and HA gateway to ensure better traceability and context in logs.
- Refactored the configuration loading process to streamline environment variable handling and defaults.
- Stubbed out switch control methods in the gRPC adapter, indicating future implementation plans.
- Enhanced telemetry setup to ensure proper initialization and shutdown procedures for observability.
2026-04-09 06:00:59 +09:00

74 lines
1.6 KiB
Go

package app
import (
"context"
"strings"
"sync"
"gitea.nik4nao.com/nik/home-services/ha-gateway/internal/core/domain"
"gitea.nik4nao.com/nik/home-services/ha-gateway/internal/core/ports/driven"
)
type SwitchApp struct {
ha driven.HAClient
mu sync.RWMutex
cache []domain.Switch
}
// NewSwitchApp constructs the switch application service.
func NewSwitchApp(ha driven.HAClient) *SwitchApp {
return &SwitchApp{ha: ha}
}
// Refresh repopulates the switch cache from the full Home Assistant state list.
func (a *SwitchApp) Refresh(ctx context.Context) error {
all, err := a.ha.ListStates(ctx)
if err != nil {
return err
}
var switches []domain.Switch
for _, s := range all {
if !strings.HasPrefix(s.EntityID, "switch.") {
continue
}
switches = append(switches, haStateToSwitch(s))
}
a.mu.Lock()
a.cache = switches
a.mu.Unlock()
return nil
}
// ListSwitches returns cached switch discovery data, refreshing lazily on first use.
func (a *SwitchApp) ListSwitches(ctx context.Context) ([]domain.Switch, error) {
a.mu.RLock()
c := a.cache
a.mu.RUnlock()
if c == nil {
if err := a.Refresh(ctx); err != nil {
return nil, err
}
a.mu.RLock()
c = a.cache
a.mu.RUnlock()
}
return c, nil
}
// haStateToSwitch extracts the subset of attributes needed for switch discovery.
func haStateToSwitch(s *driven.HAState) domain.Switch {
sw := domain.Switch{
EntityID: domain.EntityID(s.EntityID),
State: s.State,
}
if v, ok := s.Attributes["friendly_name"].(string); ok {
sw.FriendlyName = v
}
if v, ok := s.Attributes["device_class"].(string); ok {
sw.DeviceClass = v
}
return sw
}