diff --git a/arena.go b/arena.go index 1bf4624..20d98cb 100644 --- a/arena.go +++ b/arena.go @@ -14,7 +14,7 @@ import ( const ( arenaLoopPeriodMs = 10 - dsPacketPeriodMs = 250 + dsPacketPeriodMs = 100 matchEndScoreDwellSec = 3 ) @@ -338,6 +338,14 @@ func (arena *Arena) StartMatch() error { 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 } return err diff --git a/displays.go b/displays.go index 5c54e23..69e625e 100644 --- a/displays.go +++ b/displays.go @@ -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 + } +} diff --git a/driver_station_connection.go b/driver_station_connection.go index 8559da1..fc9037a 100644 --- a/driver_station_connection.go +++ b/driver_station_connection.go @@ -20,31 +20,33 @@ const driverStationProtocolVersion = "11191100" const driverStationLinkTimeoutMs = 500 type DriverStationStatus struct { - TeamId int - AllianceStation string - DsLinked bool - RobotLinked bool - Auto bool - Enabled bool - EmergencyStop bool - BatteryVoltage float64 - DsVersion string - PacketCount int - MissedPacketCount int - DsRobotTripTimeMs int + TeamId int + AllianceStation string + DsLinked bool + RobotLinked bool + Auto bool + Enabled bool + EmergencyStop bool + BatteryVoltage float64 + DsVersion string + PacketCount int + MissedPacketCount int + MissedPacketOffset int + DsRobotTripTimeMs int } type DriverStationConnection struct { - TeamId int - AllianceStation string - Auto bool - Enabled bool - EmergencyStop bool - DriverStationStatus *DriverStationStatus - LastPacketTime time.Time - LastRobotLinkedTime time.Time - conn net.Conn - packetCount int + TeamId int + AllianceStation string + Auto bool + Enabled bool + EmergencyStop bool + DriverStationStatus *DriverStationStatus + LastPacketTime time.Time + LastRobotLinkedTime time.Time + SecondsSinceLastRobotLink float64 + conn net.Conn + packetCount int } // Opens a UDP connection for communicating to the driver station. @@ -105,6 +107,7 @@ func ListenForDsPackets(listener *net.UDPConn) { if dsStatus.RobotLinked { dsConn.LastRobotLinkedTime = time.Now() } + dsConn.SecondsSinceLastRobotLink = time.Since(dsConn.LastRobotLinkedTime).Seconds() } } } diff --git a/static/audio/match_endgame.wav b/static/audio/match_endgame.wav index 291bb9f..1060473 100644 Binary files a/static/audio/match_endgame.wav and b/static/audio/match_endgame.wav differ diff --git a/static/css/cheesy-arena.css b/static/css/cheesy-arena.css index b4ff139..9210c23 100644 --- a/static/css/cheesy-arena.css +++ b/static/css/cheesy-arena.css @@ -41,18 +41,21 @@ .modal-large { 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; color: #000; border: 1px solid #999; border-radius: 4px; padding: 0px; - width: 40px; + width: 45px; height: 27px; line-height: 25px; font-size: 14px; margin: 0 auto; } +.trip-time, .packet-loss { + width: 90px; +} .bypass-status { cursor: pointer; } diff --git a/static/js/fta_display.js b/static/js/fta_display.js new file mode 100644 index 0000000..03d39bd --- /dev/null +++ b/static/js/fta_display.js @@ -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); } + }); +}); diff --git a/templates/base.html b/templates/base.html index 47f3dfe..8c4a16a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -57,13 +57,14 @@