From 5eae78ec8f85d0d329bd289bed169e5fe3bfd340 Mon Sep 17 00:00:00 2001
From: Christian Pointner <equinox@helsinki.at>
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