132 lines
3.2 KiB
Go
132 lines
3.2 KiB
Go
// Copyright 2024 Joshua Rich <joshua.rich@gmail.com>.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package hass
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
|
|
"github.com/joshuar/go-hass-agent/internal/hass/api"
|
|
"github.com/joshuar/go-hass-agent/internal/hass/sensor"
|
|
"github.com/joshuar/go-hass-agent/internal/logging"
|
|
)
|
|
|
|
const (
|
|
Registered responseStatus = iota + 1
|
|
Updated
|
|
Disabled
|
|
Failed
|
|
)
|
|
|
|
type responseStatus int
|
|
|
|
type response struct {
|
|
ErrorDetails *api.ResponseError `json:"error,omitempty"`
|
|
IsSuccess bool `json:"success,omitempty"`
|
|
}
|
|
|
|
func (r *response) Status() (responseStatus, error) {
|
|
if r.IsSuccess || r.ErrorDetails == nil {
|
|
return Updated, nil
|
|
}
|
|
|
|
return Failed, r.ErrorDetails
|
|
}
|
|
|
|
type sensorUpdateReponse struct {
|
|
response
|
|
IsDisabled bool `json:"is_disabled,omitempty"`
|
|
}
|
|
|
|
func (u *sensorUpdateReponse) Status() (responseStatus, error) {
|
|
switch {
|
|
case !u.IsSuccess:
|
|
return Failed, u.ErrorDetails
|
|
case u.IsDisabled:
|
|
return Disabled, u.ErrorDetails
|
|
default:
|
|
return Updated, nil
|
|
}
|
|
}
|
|
|
|
type bulkSensorUpdateResponse map[string]sensorUpdateReponse
|
|
|
|
func (u bulkSensorUpdateResponse) Process(ctx context.Context, details sensor.Entity) {
|
|
for id, sensorReponse := range u {
|
|
status, err := sensorReponse.Status()
|
|
|
|
switch status {
|
|
case Failed:
|
|
logging.FromContext(ctx).Warn("Sensor update failed.",
|
|
slog.String("id", id),
|
|
slog.Any("error", err))
|
|
|
|
return
|
|
case Disabled:
|
|
// Already disabled in registry, nothing to do.
|
|
if sensorRegistry.IsDisabled(id) {
|
|
return
|
|
}
|
|
// Disable in registry.
|
|
logging.FromContext(ctx).
|
|
Info("Sensor is disabled in Home Assistant. Setting disabled in local registry.",
|
|
slog.String("id", id))
|
|
|
|
if err := sensorRegistry.SetDisabled(id, true); err != nil {
|
|
logging.FromContext(ctx).Warn("Unable to disable sensor in registry.",
|
|
slog.String("id", id),
|
|
slog.Any("error", err))
|
|
}
|
|
case Updated:
|
|
logging.FromContext(ctx).
|
|
Debug("Sensor updated.",
|
|
sensorLogAttrs(details))
|
|
}
|
|
|
|
// Add the sensor update to the tracker.
|
|
if err := sensorTracker.Add(&details); err != nil {
|
|
logging.FromContext(ctx).Warn("Unable to update sensor state in tracker.",
|
|
slog.String("id", id),
|
|
slog.Any("error", err))
|
|
}
|
|
}
|
|
}
|
|
|
|
type registrationResponse response
|
|
|
|
func (r *registrationResponse) Status() (responseStatus, error) {
|
|
if r.IsSuccess {
|
|
return Registered, nil
|
|
}
|
|
|
|
return Failed, r.ErrorDetails
|
|
}
|
|
|
|
func (r *registrationResponse) Process(ctx context.Context, details sensor.Entity) {
|
|
status, err := r.Status()
|
|
|
|
switch status {
|
|
case Failed:
|
|
logging.FromContext(ctx).Warn("Sensor registration failed.",
|
|
slog.String("id", details.ID),
|
|
slog.Any("error", err))
|
|
|
|
return
|
|
case Registered:
|
|
// Set registration status in registry.
|
|
err = sensorRegistry.SetRegistered(details.ID, true)
|
|
if err != nil {
|
|
logging.FromContext(ctx).Warn("Unable to set sensor registration in registry.",
|
|
slog.String("id", details.ID),
|
|
slog.Any("error", err))
|
|
}
|
|
// Add the sensor update to the tracker.
|
|
if err := sensorTracker.Add(&details); err != nil {
|
|
logging.FromContext(ctx).Warn("Unable to update sensor state in tracker.",
|
|
slog.String("id", details.ID),
|
|
slog.Any("error", err))
|
|
}
|
|
}
|
|
}
|