Added fancy LED functionality.

This commit is contained in:
Patrick Fairbank
2014-08-28 00:12:45 -07:00
parent d5a7e241c3
commit c082c39d81
5 changed files with 223 additions and 29 deletions

View File

@@ -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)
}

170
lights.go
View File

@@ -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()
}
}

View File

@@ -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)
}

View File

@@ -1,7 +1,7 @@
{{define "title"}}Field Configuration{{end}}
{{define "body"}}
<div class="row">
<div class="col-lg-4 col-lg-offset-4">
<div class="col-lg-4 col-lg-offset-2">
<div class="well">
<legend>Alliance Station Displays</legend>
{{range $displayId, $station := .AllianceStationDisplays}}
@@ -29,6 +29,69 @@
</div>
</div>
</div>
<div class="col-lg-4">
<div class="well">
<form class="" action="/setup/field/lights" method="POST">
Light Control
<div class="form-group">
<div class="radio">
<label>
<input type="radio" name="mode" value="off" onclick="this.form.submit()"
{{if eq .LightsMode "off"}}checked{{end}}>Off
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="all_white" onclick="this.form.submit()"
{{if eq .LightsMode "all_white"}}checked{{end}}>All White
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="all_red" onclick="this.form.submit()"
{{if eq .LightsMode "all_red"}}checked{{end}}>All Red
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="all_blue" onclick="this.form.submit()"
{{if eq .LightsMode "all_blue"}}checked{{end}}>All Blue
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="all_green" onclick="this.form.submit()"
{{if eq .LightsMode "all_green"}}checked{{end}}>All Green
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="strobe" onclick="this.form.submit()"
{{if eq .LightsMode "strobe"}}checked{{end}}>Strobe
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="fade_red" onclick="this.form.submit()"
{{if eq .LightsMode "fade_red"}}checked{{end}}>Fade Red
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="fade_blue" onclick="this.form.submit()"
{{if eq .LightsMode "fade_blue"}}checked{{end}}>Fade Blue
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="mode" value="fade_red_blue" onclick="this.form.submit()"
{{if eq .LightsMode "fade_red_blue"}}checked{{end}}>Fade Red/Blue
</label>
</div>
</div>
</div>
</div>
</div>
</div>
{{end}}
{{define "script"}}

1
web.go
View File

@@ -131,6 +131,7 @@ func newHandler() http.Handler {
router.HandleFunc("/setup/field", FieldGetHandler).Methods("GET")
router.HandleFunc("/setup/field", FieldPostHandler).Methods("POST")
router.HandleFunc("/setup/field/reload_displays", FieldReloadDisplaysHandler).Methods("GET")
router.HandleFunc("/setup/field/lights", FieldLightsPostHandler).Methods("POST")
router.HandleFunc("/setup/lower_thirds", LowerThirdsGetHandler).Methods("GET")
router.HandleFunc("/setup/lower_thirds", LowerThirdsPostHandler).Methods("POST")
router.HandleFunc("/setup/sponsor_slides", SponsorSlidesGetHandler).Methods("GET")