succd: split out http server, daemon state, daemon controller

This improves the structure of the code, separating the data/control
interface out and then implementing the http interface as a user of this
interface.
This commit is contained in:
Serge Bazanski 2024-09-28 08:10:33 +02:00
parent 3ec6fd1d1b
commit 8f7ec7e141
5 changed files with 190 additions and 180 deletions

View file

@ -4,21 +4,18 @@ import (
"context"
"errors"
"fmt"
"math"
"sync"
"time"
"k8s.io/klog"
)
// daemon is the main state of the succdaemon.
// daemon is the main service of the succdaemon.
type daemon struct {
// adcPirani is the adc implementation returning the voltage of the Pfeiffer
// Pirani gauge.
adcPirani adc
safety safetyStatus
gpioDiffusionPump gpio
gpioRoughingPump gpio
gpioBtnPumpDown gpio
@ -26,27 +23,9 @@ type daemon struct {
gpioBelowRough gpio
gpioBelowHigh gpio
// mu guards state variables below.
// mu guards the state below.
mu sync.RWMutex
// adcPiraniVolts is a moving window of read ADC values, used to calculate a
// moving average.
adcPiraniVolts []float32
rpOn bool
dpOn bool
vent momentaryOutput
pumpdown momentaryOutput
aboveRough thresholdOutput
aboveHigh thresholdOutput
}
type safetyStatus struct {
// failsafe mode is enabled when the pirani gauge appears to be
// disconnected, and is disabled only when an atmosphere is read.
failsafe bool
// highPressure mode is enabled when the pressure reading is above 1e-1
// mbar, locking out the diffusion pump from being enabled.
highPressure bool
daemonState
}
// momentaryOutput is an output that can be triggered for 500ms.
@ -127,7 +106,7 @@ func (d *daemon) processOnce(_ context.Context) error {
d.pumpdown.process()
d.vent.process()
_, mbar := d.piraniUnlocked()
_, mbar := d.daemonState.pirani()
d.aboveRough.process(float64(mbar))
d.aboveHigh.process(float64(mbar))
@ -201,116 +180,3 @@ func (d *daemon) processOnce(_ context.Context) error {
return nil
}
type piraniDetection uint
const (
// piraniDetectionUnknown means the system isn't yet sure whether the pirani
// gauge is connected.
piraniDetectionUnknown piraniDetection = iota
// piraniDetectionConnected means the system assumes the pirani gauge is
// connected.
piraniDetectionConnected = iota
// piraniDetectionDisconnected means the system assumes the pirani gauge is
// disconnected.
piraniDetectionDisconnected = iota
)
// piraniDetection guesses whether the pirani gauge is connected.
func (d *daemon) piraniDetection() piraniDetection {
if len(d.adcPiraniVolts) < 3 {
return piraniDetectionUnknown
}
volts := float32(0.0)
for _, v := range d.adcPiraniVolts[len(d.adcPiraniVolts)-3:] {
volts += v
}
volts /= 3.0
bar := math.Pow(10.0, float64(volts)-8.5)
mbar := float32(bar * 1000.0)
if mbar < 4e-6 {
return piraniDetectionDisconnected
}
return piraniDetectionConnected
}
// pirani returns the Pirani gauge voltage and pressure.
func (d *daemon) pirani() (volts float32, mbar float32) {
d.mu.RLock()
volts, mbar = d.piraniUnlocked()
d.mu.RUnlock()
return
}
func (d *daemon) piraniUnlocked() (volts float32, mbar float32) {
volts = 0.0
for _, v := range d.adcPiraniVolts {
volts += v
}
if len(d.adcPiraniVolts) != 0 {
volts /= float32(len(d.adcPiraniVolts))
}
// Per Pirani probe docs.
bar := math.Pow(10.0, float64(volts)-8.5)
mbar = float32(bar * 1000.0)
return
}
// rpSet enables/disables the roughing pump.
func (d *daemon) rpSet(state bool) {
d.mu.Lock()
defer d.mu.Unlock()
d.rpOn = state
}
// rpGet returns whether the roughing pump is enabled/disabled.
func (d *daemon) rpGet() bool {
d.mu.RLock()
defer d.mu.RUnlock()
return d.rpOn
}
// dpSet enables/disables the diffusion pump.
func (d *daemon) dpSet(state bool) {
d.mu.Lock()
defer d.mu.Unlock()
d.dpOn = state
}
// dpGet returns whether the diffusion pump is enabled/disabled.
func (d *daemon) dpGet() bool {
d.mu.RLock()
defer d.mu.RUnlock()
return d.dpOn
}
func (d *daemon) vacuumStatusGet() (rough, high bool) {
d.mu.RLock()
defer d.mu.RUnlock()
rough = !d.aboveRough.output
high = !d.aboveHigh.output
return
}
func (d *daemon) safetyStatusGet() safetyStatus {
d.mu.RLock()
defer d.mu.RUnlock()
return d.safety
}
// pumpDownPressed toggles the pump down relay for 500ms.
func (d *daemon) pumpDownPress() {
d.mu.Lock()
defer d.mu.Unlock()
d.pumpdown.trigger()
}
// ventPress toggles the vent relay for 500ms.
func (d *daemon) ventPress() {
d.mu.Lock()
defer d.mu.Unlock()
d.vent.trigger()
}