package alamo import ( "context" "encoding/json" "fmt" "time" "onehouse/driver" "onehouse/protocol" ) type thermostatState struct { settings Thermostat queue <-chan []driver.Command ledger *driver.Ledger publisher *driver.Publisher missed int } func (s *thermostatState) descriptor(ctx context.Context) error { err := s.publisher.Descriptor(ctx, s.settings.DeviceID, protocol.Metadata{}, protocol.DescriptorPayload{ Manufacturer: "alamo", Model: "slim-wifi", Firmware: "unknown", Capabilities: []protocol.Capability{{ ID: "control", Type: "floor-heating", ReportsState: true, AcceptsCommands: true, }}, }) if err != nil { return fmt.Errorf("publish descriptor: %w", err) } return nil } func (s *thermostatState) record(ctx context.Context, state State, observedAt time.Time, causationID string) error { s.missed = 0 metadata := protocol.Metadata{ SentAt: &observedAt, CausationID: causationID, } err := s.publisher.Availability(ctx, s.settings.DeviceID, protocol.Metadata{SentAt: &observedAt}, protocol.AvailabilityPayload{Status: "online"}) if err != nil { return fmt.Errorf("publish thermostat contact: %w", err) } value, err := json.Marshal(newReportedControl(state)) if err != nil { return fmt.Errorf("encode thermostat feedback: %w", err) } err = s.publisher.Reported(ctx, s.settings.DeviceID, "control", metadata, protocol.ValuePayload{Value: value}) if err != nil { return fmt.Errorf("publish thermostat feedback: %w", err) } return nil } func (s *thermostatState) miss(ctx context.Context) error { s.missed = min(s.missed+1, 3) if s.missed < 3 { return nil } err := s.publisher.Availability(ctx, s.settings.DeviceID, protocol.Metadata{}, protocol.AvailabilityPayload{Status: "offline"}) if err != nil { return fmt.Errorf("publish offline: %w", err) } return nil } func (s *thermostatState) result(ctx context.Context, command driver.Command, payload protocol.ResultPayload) error { record, err := s.ledger.Remember(command.Metadata.MessageID, payload) if err != nil { return fmt.Errorf("remember thermostat result: %w", err) } err = s.publisher.Result(ctx, s.settings.DeviceID, command.Metadata.MessageID, record.Metadata, record.Payload) if err != nil { return fmt.Errorf("publish thermostat result: %w", err) } return nil }