Merge branch 'austin_2014-08-23'

This commit is contained in:
Patrick Fairbank
2014-08-23 23:42:30 -07:00
9 changed files with 177 additions and 28 deletions

View File

@@ -14,7 +14,7 @@ import (
const ( const (
arenaLoopPeriodMs = 10 arenaLoopPeriodMs = 10
dsPacketPeriodMs = 250 dsPacketPeriodMs = 100
matchEndScoreDwellSec = 3 matchEndScoreDwellSec = 3
) )
@@ -338,6 +338,14 @@ func (arena *Arena) StartMatch() error {
db.SaveMatch(arena.currentMatch) db.SaveMatch(arena.currentMatch)
} }
// Save the missed packet count to subtract it from the running count.
for _, allianceStation := range arena.AllianceStations {
if allianceStation.DsConn != nil {
allianceStation.DsConn.DriverStationStatus.MissedPacketOffset =
allianceStation.DsConn.DriverStationStatus.MissedPacketCount
}
}
arena.MatchState = START_MATCH arena.MatchState = START_MATCH
} }
return err return err

View File

@@ -1118,3 +1118,21 @@ func AllianceStationDisplayWebsocketHandler(w http.ResponseWriter, r *http.Reque
} }
} }
} }
// Renders the FTA diagnostic display.
func FtaDisplayHandler(w http.ResponseWriter, r *http.Request) {
template := template.New("").Funcs(templateHelpers)
_, err := template.ParseFiles("templates/fta_display.html", "templates/base.html")
if err != nil {
handleWebErr(w, err)
return
}
data := struct {
*EventSettings
}{eventSettings}
err = template.ExecuteTemplate(w, "base", data)
if err != nil {
handleWebErr(w, err)
return
}
}

View File

@@ -20,31 +20,33 @@ const driverStationProtocolVersion = "11191100"
const driverStationLinkTimeoutMs = 500 const driverStationLinkTimeoutMs = 500
type DriverStationStatus struct { type DriverStationStatus struct {
TeamId int TeamId int
AllianceStation string AllianceStation string
DsLinked bool DsLinked bool
RobotLinked bool RobotLinked bool
Auto bool Auto bool
Enabled bool Enabled bool
EmergencyStop bool EmergencyStop bool
BatteryVoltage float64 BatteryVoltage float64
DsVersion string DsVersion string
PacketCount int PacketCount int
MissedPacketCount int MissedPacketCount int
DsRobotTripTimeMs int MissedPacketOffset int
DsRobotTripTimeMs int
} }
type DriverStationConnection struct { type DriverStationConnection struct {
TeamId int TeamId int
AllianceStation string AllianceStation string
Auto bool Auto bool
Enabled bool Enabled bool
EmergencyStop bool EmergencyStop bool
DriverStationStatus *DriverStationStatus DriverStationStatus *DriverStationStatus
LastPacketTime time.Time LastPacketTime time.Time
LastRobotLinkedTime time.Time LastRobotLinkedTime time.Time
conn net.Conn SecondsSinceLastRobotLink float64
packetCount int conn net.Conn
packetCount int
} }
// Opens a UDP connection for communicating to the driver station. // Opens a UDP connection for communicating to the driver station.
@@ -105,6 +107,7 @@ func ListenForDsPackets(listener *net.UDPConn) {
if dsStatus.RobotLinked { if dsStatus.RobotLinked {
dsConn.LastRobotLinkedTime = time.Now() dsConn.LastRobotLinkedTime = time.Now()
} }
dsConn.SecondsSinceLastRobotLink = time.Since(dsConn.LastRobotLinkedTime).Seconds()
} }
} }
} }

Binary file not shown.

View File

@@ -41,18 +41,21 @@
.modal-large { .modal-large {
width: 60%; width: 60%;
} }
.ds-status, .robot-status, .battery-status, .bypass-status { .ds-status, .robot-status, .battery-status, .bypass-status, .bypass-status-fta, .trip-time, .packet-loss {
background-color: #aaa; background-color: #aaa;
color: #000; color: #000;
border: 1px solid #999; border: 1px solid #999;
border-radius: 4px; border-radius: 4px;
padding: 0px; padding: 0px;
width: 40px; width: 45px;
height: 27px; height: 27px;
line-height: 25px; line-height: 25px;
font-size: 14px; font-size: 14px;
margin: 0 auto; margin: 0 auto;
} }
.trip-time, .packet-loss {
width: 90px;
}
.bypass-status { .bypass-status {
cursor: pointer; cursor: pointer;
} }

62
static/js/fta_display.js Normal file
View File

@@ -0,0 +1,62 @@
// Copyright 2014 Team 254. All Rights Reserved.
// Author: austin.linux@gmail.com (Austin Schuh)
// Author: pat@patfairbank.com (Patrick Fairbank)
//
// Client-side logic for the FTA diagnostic display.
var websocket;
var handleStatus = function(data) {
// Update the team status view.
$.each(data.AllianceStations, function(station, stationStatus) {
if (stationStatus.DsConn) {
$("#status" + station + " .team").text(stationStatus.DsConn.TeamId);
var dsStatus = stationStatus.DsConn.DriverStationStatus;
$("#status" + station + " .ds-status").attr("data-status-ok", dsStatus.DsLinked);
$("#status" + station + " .robot-status").attr("data-status-ok", dsStatus.RobotLinked);
if (stationStatus.DsConn.SecondsSinceLastRobotLink > 1 && stationStatus.DsConn.SecondsSinceLastRobotLink < 1000) {
$("#status" + station + " .robot-status").text(stationStatus.DsConn.SecondsSinceLastRobotLink.toFixed());
} else {
$("#status" + station + " .robot-status").text("");
}
$("#status" + station + " .battery-status").attr("data-status-ok",
dsStatus.BatteryVoltage > 6 && dsStatus.RobotLinked);
$("#status" + station + " .battery-status").text(dsStatus.BatteryVoltage.toFixed(1) + "V");
$("#status" + station + " .trip-time").attr("data-status-ok", true);
$("#status" + station + " .trip-time").text(dsStatus.DsRobotTripTimeMs.toFixed(1) + "ms");
$("#status" + station + " .packet-loss").attr("data-status-ok", true);
$("#status" + station + " .packet-loss").text(dsStatus.MissedPacketCount - dsStatus.MissedPacketOffset);
} else {
$("#status" + station + " .ds-status").attr("data-status-ok", "");
$("#status" + station + " .robot-status").attr("data-status-ok", "");
$("#status" + station + " .robot-status").text("");
$("#status" + station + " .battery-status").attr("data-status-ok", "");
$("#status" + station + " .battery-status").text("");
$("#status" + station + " .trip-time").attr("data-status-ok", "");
$("#status" + station + " .trip-time").text("");
$("#status" + station + " .packet-loss").attr("data-status-ok", "");
$("#status" + station + " .packet-loss").text("");
}
if (stationStatus.EmergencyStop) {
$("#status" + station + " .bypass-status-fta").attr("data-status-ok", false);
$("#status" + station + " .bypass-status-fta").text("ES");
} else if (stationStatus.Bypass) {
$("#status" + station + " .bypass-status-fta").attr("data-status-ok", false);
$("#status" + station + " .bypass-status-fta").text("B");
} else {
$("#status" + station + " .bypass-status-fta").attr("data-status-ok", true);
$("#status" + station + " .bypass-status-fta").text("");
}
});
};
$(function() {
// Activate tooltips above the status headers.
$("[data-toggle=tooltip]").tooltip({"placement": "top"});
// Set up the websocket back to the server.
websocket = new CheesyWebsocket("/match_play/websocket", {
status: function(event) { handleStatus(event.data); }
});
});

View File

@@ -57,13 +57,14 @@
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Display</a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Display</a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="/displays/audience">Audience</a></li> <li><a href="/displays/alliance_station">Alliance Station</a></li>
<li><a href="/displays/pit">Pit</a></li>
<li><a href="/displays/announcer">Announcer</a></li> <li><a href="/displays/announcer">Announcer</a></li>
<li><a href="/displays/audience">Audience</a></li>
<li><a href="/displays/fta">FTA</a></li>
<li><a href="/displays/pit">Pit</a></li>
<li><a href="/displays/referee">Referee</a></li> <li><a href="/displays/referee">Referee</a></li>
<li><a href="/displays/scoring/red">Scoring &ndash; Red</a></li> <li><a href="/displays/scoring/red">Scoring &ndash; Red</a></li>
<li><a href="/displays/scoring/blue">Scoring &ndash; Blue</a></li> <li><a href="/displays/scoring/blue">Scoring &ndash; Blue</a></li>
<li><a href="/displays/alliance_station">Alliance Station</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,53 @@
{{define "title"}}FTA Display{{end}}
{{define "body"}}
<div class="row">
<div class="col-lg-12">
<div class="row text-center">
<div class="col-lg-6 well well-darkblue">
<div class="row form-group">
<div class="col-lg-3">Blue Teams</div>
<div class="col-lg-1" data-toggle="tooltip" title="Driver Station">DS</div>
<div class="col-lg-1" data-toggle="tooltip" title="Robot Status/Time Since Last Link">R</div>
<div class="col-lg-1" data-toggle="tooltip" title="Battery">Bat</div>
<div class="col-lg-1" data-toggle="tooltip" title="Bypassed/Disabled">Byp</div>
<div class="col-lg-2" data-toggle="tooltip" title="Average Trip Time">Trip Time</div>
<div class="col-lg-2" data-toggle="tooltip" title="Packet Loss">Lost Pack</div>
</div>
{{template "ftaTeam" dict "color" "B" "position" 1 "data" .}}
{{template "ftaTeam" dict "color" "B" "position" 2 "data" .}}
{{template "ftaTeam" dict "color" "B" "position" 3 "data" .}}
</div>
<div class="col-lg-6 well well-darkred">
<div class="row form-group">
<div class="col-lg-3">Red Teams</div>
<div class="col-lg-1" data-toggle="tooltip" title="Driver Station">DS</div>
<div class="col-lg-1" data-toggle="tooltip" title="Robot Status/Time Since Last Link">R</div>
<div class="col-lg-1" data-toggle="tooltip" title="Battery">Bat</div>
<div class="col-lg-1" data-toggle="tooltip" title="Bypassed/Disabled">Byp</div>
<div class="col-lg-2" data-toggle="tooltip" title="Average Trip Time">Trip Time</div>
<div class="col-lg-2" data-toggle="tooltip" title="Packet Loss">Lost Pack</div>
</div>
{{template "ftaTeam" dict "color" "R" "position" 3 "data" .}}
{{template "ftaTeam" dict "color" "R" "position" 2 "data" .}}
{{template "ftaTeam" dict "color" "R" "position" 1 "data" .}}
</div>
</div>
<br />
</div>
</div>
{{end}}
{{define "script"}}
<script src="/static/js/fta_display.js"></script>
{{end}}
{{define "ftaTeam"}}
<div class="row form-group" id="status{{.color}}{{.position}}">
<div class="col-lg-1">{{.position}} </div>
<div class="col-lg-2"><div class="team"></div></div>
<div class="col-lg-1 col-no-padding"><div class="ds-status"></div></div>
<div class="col-lg-1 col-no-padding"><div class="robot-status"></div></div>
<div class="col-lg-1 col-no-padding"><div class="battery-status"></div></div>
<div class="col-lg-1 col-no-padding"><div class="bypass-status-fta"></div></div>
<div class="col-lg-2 col-no-padding"><div class="trip-time" ></div></div>
<div class="col-lg-2 col-no-padding"><div class="packet-loss" ></div></div>
</div>
{{end}}

1
web.go
View File

@@ -152,6 +152,7 @@ func newHandler() http.Handler {
router.HandleFunc("/displays/referee/websocket", RefereeDisplayWebsocketHandler).Methods("GET") router.HandleFunc("/displays/referee/websocket", RefereeDisplayWebsocketHandler).Methods("GET")
router.HandleFunc("/displays/alliance_station", AllianceStationDisplayHandler).Methods("GET") router.HandleFunc("/displays/alliance_station", AllianceStationDisplayHandler).Methods("GET")
router.HandleFunc("/displays/alliance_station/websocket", AllianceStationDisplayWebsocketHandler).Methods("GET") router.HandleFunc("/displays/alliance_station/websocket", AllianceStationDisplayWebsocketHandler).Methods("GET")
router.HandleFunc("/displays/fta", FtaDisplayHandler).Methods("GET")
router.HandleFunc("/api/matches/{type}", MatchesApiHandler).Methods("GET") router.HandleFunc("/api/matches/{type}", MatchesApiHandler).Methods("GET")
router.HandleFunc("/api/rankings", RankingsApiHandler).Methods("GET") router.HandleFunc("/api/rankings", RankingsApiHandler).Methods("GET")
router.HandleFunc("/", IndexHandler).Methods("GET") router.HandleFunc("/", IndexHandler).Methods("GET")