diff --git a/arena.go b/arena.go index 20d98cb..f026d43 100644 --- a/arena.go +++ b/arena.go @@ -530,7 +530,7 @@ func (arena *Arena) handleLighting(alliance string, score *RealtimeScore) { arena.lights.ClearPedestal(alliance) } arena.lights.SetAssistGoal(alliance, score.CurrentCycle.Assists) - default: + case POST_MATCH: arena.lights.ClearGoal(alliance) arena.lights.ClearPedestal(alliance) } diff --git a/lights.go b/lights.go index 748a9e2..41a7e69 100644 --- a/lights.go +++ b/lights.go @@ -8,9 +8,10 @@ package main import ( "log" "net" + "time" ) -type LightPacket [24]byte +type LightPacket [32]byte type Lights struct { connections map[string]*net.Conn @@ -18,28 +19,55 @@ type Lights struct { oldPackets map[string]*LightPacket hotGoal string newConnections bool + currentMode string + animationCount int } -func (lightPacket *LightPacket) setColor(channel int, color string) { +func (lightPacket *LightPacket) setColorFade(channel int, color string, fade byte) { switch color { + case "off": + lightPacket.setRgbFade(channel, 0, 0, 0, fade) + case "white": + lightPacket.setRgbFade(channel, 15, 15, 15, fade) case "red": - lightPacket.setRgb(channel, 15, 0, 0) + lightPacket.setRgbFade(channel, 15, 0, 0, fade) case "blue": - lightPacket.setRgb(channel, 0, 0, 15) + lightPacket.setRgbFade(channel, 0, 0, 15, fade) + case "green": + lightPacket.setRgbFade(channel, 0, 15, 0, fade) case "yellow": - lightPacket.setRgb(channel, 15, 11, 0) - default: - lightPacket.setRgb(channel, 0, 0, 0) + lightPacket.setRgbFade(channel, 15, 11, 0, fade) + case "darkred": + lightPacket.setRgbFade(channel, 1, 0, 0, fade) + case "darkblue": + lightPacket.setRgbFade(channel, 0, 0, 1, fade) } } -func (lightPacket *LightPacket) setRgb(channel int, red byte, green byte, blue byte) { - lightPacket[channel*3] = red - lightPacket[channel*3+1] = green - lightPacket[channel*3+2] = blue +func (lightPacket *LightPacket) setColor(channel int, color string) { + lightPacket.setColorFade(channel, color, 0) +} + +func (lightPacket *LightPacket) setRgbFade(channel int, red byte, green byte, blue byte, fade byte) { + lightPacket[channel*4] = red + lightPacket[channel*4+1] = green + lightPacket[channel*4+2] = blue + lightPacket[channel*4+3] = fade +} + +func (lightPacket *LightPacket) setAllColor(color string) { + lightPacket.setAllColorFade(color, 0) +} + +func (lightPacket *LightPacket) setAllColorFade(color string, fade byte) { + for i := 0; i < 8; i++ { + lightPacket.setColorFade(i, color, fade) + } } func (lights *Lights) Setup() error { + lights.currentMode = "off" + err := lights.SetupConnections() if err != nil { return err @@ -53,6 +81,14 @@ func (lights *Lights) Setup() error { lights.oldPackets["blue"] = &LightPacket{} lights.sendLights() + + // Set up a goroutine to animate the lights when necessary. + ticker := time.NewTicker(time.Millisecond * 50) + go func() { + for _ = range ticker.C { + lights.animate() + } + }() return nil } @@ -80,9 +116,9 @@ func (lights *Lights) SetupConnections() error { func (lights *Lights) SetHotGoal(alliance string, leftSide bool) { if leftSide { - lights.packets[alliance].setRgb(0, 0, 0, 0) - lights.packets[alliance].setRgb(1, 0, 0, 0) - lights.packets[alliance].setRgb(2, 0, 0, 0) + lights.packets[alliance].setColor(0, "off") + lights.packets[alliance].setColor(1, "off") + lights.packets[alliance].setColor(2, "off") lights.packets[alliance].setColor(3, "yellow") lights.packets[alliance].setColor(4, "yellow") lights.packets[alliance].setColor(5, "yellow") @@ -91,21 +127,21 @@ func (lights *Lights) SetHotGoal(alliance string, leftSide bool) { lights.packets[alliance].setColor(0, "yellow") lights.packets[alliance].setColor(1, "yellow") lights.packets[alliance].setColor(2, "yellow") - lights.packets[alliance].setRgb(3, 0, 0, 0) - lights.packets[alliance].setRgb(4, 0, 0, 0) - lights.packets[alliance].setRgb(5, 0, 0, 0) + lights.packets[alliance].setColor(3, "off") + lights.packets[alliance].setColor(4, "off") + lights.packets[alliance].setColor(5, "off") lights.hotGoal = "right" } lights.sendLights() } func (lights *Lights) SetAssistGoal(alliance string, numAssists int) { - lights.packets[alliance].setRgb(0, 0, 0, 0) - lights.packets[alliance].setRgb(1, 0, 0, 0) - lights.packets[alliance].setRgb(2, 0, 0, 0) - lights.packets[alliance].setRgb(3, 0, 0, 0) - lights.packets[alliance].setRgb(4, 0, 0, 0) - lights.packets[alliance].setRgb(5, 0, 0, 0) + lights.packets[alliance].setColor(0, "off") + lights.packets[alliance].setColor(1, "off") + lights.packets[alliance].setColor(2, "off") + lights.packets[alliance].setColor(3, "off") + lights.packets[alliance].setColor(4, "off") + lights.packets[alliance].setColor(5, "off") if numAssists > 0 { lights.packets[alliance].setColor(2, alliance) lights.packets[alliance].setColor(3, alliance) @@ -123,7 +159,12 @@ func (lights *Lights) SetAssistGoal(alliance string, numAssists int) { } func (lights *Lights) ClearGoal(alliance string) { - lights.SetAssistGoal(alliance, 0) + lights.packets[alliance].setColorFade(0, "off", 10) + lights.packets[alliance].setColorFade(1, "off", 10) + lights.packets[alliance].setColorFade(2, "off", 10) + lights.packets[alliance].setColorFade(3, "off", 10) + lights.packets[alliance].setColorFade(4, "off", 10) + lights.packets[alliance].setColorFade(5, "off", 10) } func (lights *Lights) SetPedestal(alliance string) { @@ -137,9 +178,33 @@ func (lights *Lights) SetPedestal(alliance string) { func (lights *Lights) ClearPedestal(alliance string) { if alliance == "red" { - lights.packets["blue"].setRgb(6, 0, 0, 0) + lights.packets["blue"].setColorFade(6, "off", 10) } else { - lights.packets["red"].setRgb(6, 0, 0, 0) + lights.packets["red"].setColorFade(6, "off", 10) + } + lights.sendLights() +} + +func (lights *Lights) SetMode(mode string) { + lights.currentMode = mode + lights.animationCount = 0 + + switch mode { + case "off": + lights.packets["red"].setAllColor("off") + lights.packets["blue"].setAllColor("off") + case "all_white": + lights.packets["red"].setAllColor("white") + lights.packets["blue"].setAllColor("white") + case "all_red": + lights.packets["red"].setAllColor("red") + lights.packets["blue"].setAllColor("red") + case "all_green": + lights.packets["red"].setAllColor("green") + lights.packets["blue"].setAllColor("green") + case "all_blue": + lights.packets["red"].setAllColor("blue") + lights.packets["blue"].setAllColor("blue") } lights.sendLights() } @@ -157,3 +222,56 @@ func (lights *Lights) sendLights() { } lights.newConnections = false } + +func (lights *Lights) animate() { + lights.animationCount += 1 + + switch lights.currentMode { + case "strobe": + switch lights.animationCount { + case 1: + lights.packets["red"].setAllColor("white") + lights.packets["blue"].setAllColor("off") + case 2: + lights.packets["red"].setAllColor("off") + lights.packets["blue"].setAllColor("white") + fallthrough + default: + lights.animationCount = 0 + } + lights.sendLights() + case "fade_red": + if lights.animationCount == 1 { + lights.packets["red"].setAllColorFade("red", 18) + lights.packets["blue"].setAllColorFade("red", 18) + } else if lights.animationCount == 61 { + lights.packets["red"].setAllColorFade("darkred", 18) + lights.packets["blue"].setAllColorFade("darkred", 18) + } else if lights.animationCount > 120 { + lights.animationCount = 0 + } + lights.sendLights() + case "fade_blue": + if lights.animationCount == 1 { + lights.packets["red"].setAllColorFade("blue", 18) + lights.packets["blue"].setAllColorFade("blue", 18) + } else if lights.animationCount == 61 { + lights.packets["red"].setAllColorFade("darkblue", 18) + lights.packets["blue"].setAllColorFade("darkblue", 18) + } else if lights.animationCount > 120 { + lights.animationCount = 0 + } + lights.sendLights() + case "fade_red_blue": + if lights.animationCount == 1 { + lights.packets["red"].setAllColorFade("blue", 18) + lights.packets["blue"].setAllColorFade("darkred", 18) + } else if lights.animationCount == 61 { + lights.packets["red"].setAllColorFade("darkblue", 18) + lights.packets["blue"].setAllColorFade("red", 18) + } else if lights.animationCount > 120 { + lights.animationCount = 0 + } + lights.sendLights() + } +} diff --git a/setup_field.go b/setup_field.go index cd93763..33cffb7 100644 --- a/setup_field.go +++ b/setup_field.go @@ -25,7 +25,8 @@ func FieldGetHandler(w http.ResponseWriter, r *http.Request) { data := struct { *EventSettings AllianceStationDisplays map[string]string - }{eventSettings, mainArena.allianceStationDisplays} + LightsMode string + }{eventSettings, mainArena.allianceStationDisplays, mainArena.lights.currentMode} err = template.ExecuteTemplate(w, "base", data) if err != nil { handleWebErr(w, err) @@ -57,3 +58,14 @@ func FieldReloadDisplaysHandler(w http.ResponseWriter, r *http.Request) { mainArena.reloadDisplaysNotifier.Notify(nil) http.Redirect(w, r, "/setup/field", 302) } + +// Controls the field LEDs for testing or effect. +func FieldLightsPostHandler(w http.ResponseWriter, r *http.Request) { + if auth.Authorize(r) == "" { + auth.NotifyAuthRequired(w, r) + return + } + + mainArena.lights.SetMode(r.PostFormValue("mode")) + http.Redirect(w, r, "/setup/field", 302) +} diff --git a/templates/field.html b/templates/field.html index d3ad6ed..61ad2ab 100644 --- a/templates/field.html +++ b/templates/field.html @@ -1,7 +1,7 @@ {{define "title"}}Field Configuration{{end}} {{define "body"}}