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
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
|
|
}
|
|
|