From 5eae78ec8f85d0d329bd289bed169e5fe3bfd340 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Wed, 20 Apr 2016 01:56:25 +0200 Subject: replaced snooze timer with generic settling timer diff --git a/sample-config.toml b/sample-config.toml index 8d2e2df..09bb5ad 100644 --- a/sample-config.toml +++ b/sample-config.toml @@ -10,11 +10,11 @@ inputs = [ { number = 1, server = "master", channel = "main" }, [servers] - # [servers.master] - # ctrl_dev = "/dev/ttyUSB1" - # ctrl_baud = 38400 - # heartbeat_dev = "/dev/ttyUSB2" - # heartbeat_baud = 19200 + [servers.master] + ctrl_dev = "/dev/ttyUSB1" + ctrl_baud = 38400 + heartbeat_dev = "/dev/ttyUSB2" + heartbeat_baud = 19200 # [servers.standby] # ctrl_dev = "/dev/ttyUSB3" diff --git a/src/rhctl/audio_switch.go b/src/rhctl/audio_switch.go index 41db086..3623138 100644 --- a/src/rhctl/audio_switch.go +++ b/src/rhctl/audio_switch.go @@ -98,6 +98,7 @@ type SwitchState struct { type AudioSwitch struct { port *SerialPort timeout time.Duration + Inputs ConfigSwitchInputs current *SwitchCommand timer *time.Timer unit SwitchUnitID @@ -364,6 +365,7 @@ func SwitchInit(conf *Config) (sw *AudioSwitch, err error) { sw.timeout = conf.Audioswitch.Timeout.Duration } sw.unit = conf.Audioswitch.Unit + sw.Inputs = conf.Audioswitch.Inputs sw.StateChanges = make(chan SwitchState, 16) sw.Commands = make(chan *SwitchCommand, 16) sw.Updates = make(chan SwitchUpdate, 32) diff --git a/src/rhctl/switch_control.go b/src/rhctl/switch_control.go index a044124..0c91331 100644 --- a/src/rhctl/switch_control.go +++ b/src/rhctl/switch_control.go @@ -57,6 +57,7 @@ type State struct { Switch SwitchState ActiveServer string Server map[string]ServerState + Settled bool } type CommandType uint8 @@ -89,7 +90,7 @@ type SwitchControl struct { sw *AudioSwitch servers []*PlayoutServer state State - snooze <-chan time.Time + settling *time.Timer Updates *pubsub.PubSub Commands chan *Command } @@ -103,7 +104,7 @@ func (ctrl *SwitchControl) handleCommand(cmd *Command) { cmd.Response <- fmt.Errorf("no server specified") return } - cmd.Response <- ctrl.reconcile(cmd.Args[0], false) + cmd.Response <- ctrl.reconcile(cmd.Args[0]) case CmdSwitch: if len(cmd.Args) == 0 { cmd.Response <- fmt.Errorf("no command specified") @@ -152,23 +153,39 @@ func (ctrl *SwitchControl) checkMissingOrStaleStates(maxAge time.Duration) { } func (ctrl *SwitchControl) getSwitchServerAssignment() (swsrv, swch string, err error) { - // TODO: implement this - return "", "", errors.New("not implemented") + activeInput := SwitchInputNum(0) + cnt := 0 + for idx, in := range ctrl.state.Switch.Audio[0].Inputs { + if in { + activeInput = SwitchInputNum(idx + 1) + cnt++ + } + } + if cnt != 1 || activeInput == SwitchInputNum(0) { + return "", "", errors.New("no or more than one input is active") + } + + for _, in := range ctrl.sw.Inputs { + if in.Number == activeInput { + return in.Server, in.Channel, nil + } + } + return "", "", errors.New("unknown input") } func (ctrl *SwitchControl) selectServer(server string) { // TODO: send out commands to switch } -func (ctrl *SwitchControl) reconcile(requestedServer string, snooze bool) (result bool) { - rhdl.Printf("SwitchCTRL: reconciling state... (requested server: '%s', snooze: %t)", requestedServer, snooze) +func (ctrl *SwitchControl) reconcile(requestedServer string) (result bool) { + if !ctrl.state.Settled { + return + } + + rhdl.Printf("SwitchCTRL: reconciling state... (requested server: '%s')", requestedServer) switch ctrl.state.Mood { case MoodAwakening: - if !snooze { // this not a wakeup of the snooze timer - // it's too early to take actions - let's learn a little bit more about current state - return - } if len(ctrl.servers) < 1 { ctrl.state.Mood = MoodHappy rhdl.Printf("SwitchCTRL: there are no servers configured -> now in mood: %s", ctrl.state.Mood) @@ -190,12 +207,12 @@ func (ctrl *SwitchControl) reconcile(requestedServer string, snooze bool) (resul rhl.Printf("SwitchCTRL: just woken up... switch is set to server '%s' channel '%s'", swsrv, swch) s, exists := ctrl.state.Server[swsrv] - if !exists || s.Health != ServerAlive { - rhl.Printf("SwitchCTRL: server '%s' is unknown or dead!", swsrv) + if !exists || s.Health != ServerAlive || s.Channel == "" { + rhl.Printf("SwitchCTRL: server '%s' is unknown, dead or has invalid channel!", swsrv) for name, state := range ctrl.state.Server { - if state.Health == ServerAlive { + if state.Health == ServerAlive && state.Channel != "" { ctrl.state.Mood = MoodNervous - rhl.Printf("SwitchCTRL: found another alive server -> now in mood: %s", ctrl.state.Mood) + rhl.Printf("SwitchCTRL: found another valid server -> now in mood: %s", ctrl.state.Mood) ctrl.selectServer(name) return } @@ -247,7 +264,9 @@ func (ctrl *SwitchControl) reconcile(requestedServer string, snooze bool) (resul func (ctrl *SwitchControl) Run() { rhdl.Printf("SwitchCTRL: handler running...") - ctrl.snooze = time.After(time.Minute) // TODO: hardcode value + ctrl.settling = time.NewTimer(30 * time.Second) // TODO: hardcode value + ctrl.state.Settled = false + serverStateChanges := make(chan ServerState, 8) for _, srv := range ctrl.servers { go handleServer(srv.StateChanges, serverStateChanges) @@ -257,11 +276,13 @@ func (ctrl *SwitchControl) Run() { // TODO: this should be called from reconcile but with some sort of rate-limiting... ctrl.checkMissingOrStaleStates(2 * time.Hour) // TODO: hardcoded value - ctrl.reconcile("", false) + ctrl.reconcile("") for { select { - case <-ctrl.snooze: - ctrl.reconcile("", true) + case <-ctrl.settling.C: + ctrl.state.Settled = true + ctrl.reconcile("") + ctrl.Updates.Pub(ctrl.state, "state") case update := <-ctrl.sw.Updates: rhdl.Printf("got update from switch: %+v", update) for _, srv := range ctrl.servers { @@ -272,13 +293,13 @@ func (ctrl *SwitchControl) Run() { // rhdl.Printf("got switch state update: %+v", state) ctrl.Updates.Pub(state, "switch:state") ctrl.state.Switch = state - ctrl.reconcile("", false) + ctrl.reconcile("") ctrl.Updates.Pub(ctrl.state, "state") case state := <-serverStateChanges: rhdl.Printf("got server state update: %+v", state) ctrl.Updates.Pub(state, "server:state") ctrl.state.Server[state.Name] = state - ctrl.reconcile("", false) + ctrl.reconcile("") ctrl.Updates.Pub(ctrl.state, "state") case cmd := <-ctrl.Commands: ctrl.handleCommand(cmd) diff --git a/src/rhctl/telnet.go b/src/rhctl/telnet.go index c849bd8..9d41802 100644 --- a/src/rhctl/telnet.go +++ b/src/rhctl/telnet.go @@ -55,7 +55,12 @@ func telnetCmdState(c *telgo.Client, args []string, ctrl *SwitchControl) bool { c.Sayln("%v", r) case State: s := r.(State) - c.Sayln("Mood: %v", s.Mood) + c.Say("Mood: %v", s.Mood) + if !s.Settled { + c.Sayln(" (settling)") + } else { + c.Sayln("") + } c.Sayln("Switch:") c.Sayln(" audio: (last changed: %v ago)", time.Since(s.Switch.AudioInputsChanged)) -- cgit v0.10.2