You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

62 lines
1.5 KiB

package sensor
import (
"context"
"sync"
"time"
"mqtt_washingmachine/internal/status"
)
// Sampler collects the latest valid message in each interval, independently of
// HTTP requests. Its zero value is ready to use; all methods are concurrency-safe.
type Sampler struct {
mu sync.Mutex
window status.Window
power float64
receivedAt time.Time
received bool
}
// Receive updates the pending measurement. Invalid payloads leave it untouched.
func (s *Sampler) Receive(payload []byte) error {
power, err := ParsePower(payload)
if err != nil {
return err
}
s.mu.Lock()
defer s.mu.Unlock()
s.power, s.receivedAt, s.received = power, time.Now(), true
return nil
}
// Run records one sample per tick, then clears the received flag. An interval
// without valid messages is missing; a previous measurement is never reused.
// The caller supplies the ticker and runs only one Run loop per sampler.
func (s *Sampler) Run(ctx context.Context, ticks <-chan time.Time) {
for {
select {
case <-ctx.Done():
return
case _, ok := <-ticks:
if !ok {
return
}
s.mu.Lock()
sample := status.Sample{}
if s.received {
sample = status.Sample{Power: s.power, Valid: true}
}
s.window.Add(sample)
s.received = false
s.mu.Unlock()
}
}
}
// Status returns an independent snapshot of the current window and its state.
func (s *Sampler) Status() status.Result {
s.mu.Lock()
defer s.mu.Unlock()
return status.Evaluate(s.window.Readings())
}