Files
PrintControl/go/internal/printer/state.go

116 lines
2.0 KiB
Go

package printer
import "time"
type PrintState int
const (
StateIdle PrintState = iota
StateSDPrinting
StateHostPrinting
StatePaused
StateError
)
func (p PrintState) String() string {
switch p {
case StateIdle:
return "IDLE"
case StateSDPrinting:
return "SD PRINTING"
case StateHostPrinting:
return "PRINTING"
case StatePaused:
return "PAUSED"
case StateError:
return "ERROR"
default:
return "?"
}
}
type TempPair struct {
Current float64
Target float64
}
type SDFile struct {
Name string // 8.3 short filename, what M23 takes
LongName string // long filename if firmware reports one
Size int64
}
type State struct {
Connected bool
Online bool
Firmware string
Port string
Baud int
PrintState PrintState
ErrorMsg string
Temps map[string]TempPair
SDByte int64
SDTotal int64
SDFilename string
SDStart time.Time
FeedratePct int
FlowPct int
FanPct int
BabystepZ float64
// SD card listing. SDListing is true while M20 output is being
// collected; SDFiles is the most recently completed listing.
SDFiles []SDFile
SDListing bool
}
func NewState() State {
return State{
Temps: map[string]TempPair{},
FeedratePct: 100,
FlowPct: 100,
FanPct: 0,
PrintState: StateIdle,
}
}
func (s *State) Progress() float64 {
if s.SDTotal <= 0 {
return 0
}
p := float64(s.SDByte) / float64(s.SDTotal)
if p > 1 {
return 1
}
return p
}
func (s *State) ETA() (time.Duration, bool) {
if s.PrintState != StateSDPrinting || s.SDByte <= 0 || s.SDStart.IsZero() {
return 0, false
}
elapsed := nowFn().Sub(s.SDStart)
if elapsed < 5*time.Second {
return 0, false
}
rate := float64(s.SDByte) / elapsed.Seconds()
if rate <= 0 {
return 0, false
}
remaining := float64(s.SDTotal - s.SDByte)
if remaining < 0 {
remaining = 0
}
return time.Duration(remaining/rate) * time.Second, true
}
// indirection so tests can fix time
var (
nowFn = time.Now
zeroTime = time.Time{}
)