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.
 
 
 

67 lines
1.9 KiB

// Package status evaluates laundry state from the latest three power samples.
// Power below 3 W is idle; missing samples take precedence over active readings.
package status
const windowSize = 3
// Sample represents one sampling interval. Invalid samples have no power reading.
type Sample struct {
Power float64 `json:"power"`
Valid bool `json:"valid"`
}
// Result is the status API response, with readings ordered oldest first.
type Result struct {
State string `json:"state"`
Message string `json:"message"`
Readings []Sample `json:"readings"`
}
// Window holds the last three samples. Callers synchronize concurrent access.
// The zero value is an empty window.
type Window struct {
samples [windowSize]Sample
next int
count int
}
// Add records an interval, including intervals without a valid reading.
func (w *Window) Add(sample Sample) {
w.samples[w.next] = sample
w.next = (w.next + 1) % windowSize
if w.count < windowSize {
w.count++
}
}
// Readings returns an independent snapshot, oldest first, including missing data.
func (w *Window) Readings() []Sample {
readings := make([]Sample, w.count)
for i := range w.count {
readings[i] = w.samples[(w.next-w.count+i+windowSize)%windowSize]
}
return readings
}
// Evaluate applies waiting, incomplete, running, then done precedence to a
// window's readings. An empty window serializes as [] rather than null.
func Evaluate(readings []Sample) Result {
result := Result{State: "waiting", Message: "Waiting for data...", Readings: append([]Sample{}, readings...)}
if len(readings) < windowSize {
return result
}
for _, sample := range readings {
if !sample.Valid {
result.State, result.Message = "incomplete", "Incomplete data"
return result
}
}
for _, sample := range readings {
if sample.Power >= 3 {
result.State, result.Message = "running", "Laundry not yet done"
return result
}
}
result.State, result.Message = "done", "Laundry done"
return result
}