Skip to content

Commit

Permalink
Establish initial protocol and database table for derby-timer.jar to …
Browse files Browse the repository at this point in the history
…send flag settings to server.
  • Loading branch information
jeffpiazza committed Feb 13, 2021
1 parent adbf507 commit 4c7fa4c
Show file tree
Hide file tree
Showing 12 changed files with 564 additions and 255 deletions.
617 changes: 388 additions & 229 deletions docs/Developers- Timer Messages.fodt

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions timer/src/org/jeffpiazza/derby/Flag.java
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public static Flag[] allFlags() {

public abstract boolean maybeParseXml(Element flag_element);

public abstract String typeName();

public String name() {
return name;
}
Expand All @@ -152,6 +154,8 @@ public T value() {
return value;
}

public String description() { return description; }

public String usage_string() {
return " -" + name() + ": " + description;
}
Expand All @@ -164,6 +168,7 @@ public static class BooleanFlag extends Flag<Boolean> {
public BooleanFlag(String name, String description) {
super(name, Boolean.FALSE, description);
}
public String typeName() { return "bool"; }

@Override
public int maybeParseCommandLine(String[] args, int argc) {
Expand Down Expand Up @@ -191,6 +196,7 @@ public static class StringFlag extends Flag<String> {
public StringFlag(String name, String value, String description) {
super(name, value, description);
}
public String typeName() { return "string"; }

@Override
public int maybeParseCommandLine(String[] args, int argc) {
Expand All @@ -214,6 +220,7 @@ public static class LongFlag extends Flag<Long> {
public LongFlag(String name, Long value, String description) {
super(name, value, description);
}
public String typeName() { return "long"; }

public LongFlag(String name, long value, String description) {
super(name, new Long(value), description);
Expand Down Expand Up @@ -241,6 +248,7 @@ public static class IntegerFlag extends Flag<Integer> {
public IntegerFlag(String name, Integer value, String description) {
super(name, value, description);
}
public String typeName() { return "int"; }

@Override
public int maybeParseCommandLine(String[] args, int argc) {
Expand Down
58 changes: 33 additions & 25 deletions timer/src/org/jeffpiazza/derby/HttpTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,37 +246,45 @@ public void run() {
}
}

NodeList remote_logs = response.getElementsByTagName("remote-log");
if (remote_logs.getLength() > 0) {
LogWriter.setRemoteLogging(Boolean.parseBoolean(
((Element) remote_logs.item(0)).getAttribute("send")));
}
decodeResponse(response);
}
}

if (response.getElementsByTagName("abort").getLength() > 0) {
AbortHeatCallback cb = getAbortHeatCallback();
if (cb != null) {
cb.onAbortHeat();
}
private void decodeResponse(Element response) {
NodeList remote_logs = response.getElementsByTagName("remote-log");
if (remote_logs.getLength() > 0) {
LogWriter.setRemoteLogging(Boolean.parseBoolean(
((Element) remote_logs.item(0)).getAttribute("send")));
}

if (response.getElementsByTagName("abort").getLength() > 0) {
AbortHeatCallback cb = getAbortHeatCallback();
if (cb != null) {
cb.onAbortHeat();
}
}

NodeList heatReadyNodes = response.getElementsByTagName("heat-ready");
if (heatReadyNodes.getLength() > 0) {
HeatReadyCallback cb = getHeatReadyCallback();
if (cb != null) {
Element heatReady = (Element) heatReadyNodes.item(0);
int lanemask = parseIntOrZero(heatReady.getAttribute("lane-mask"));
int roundid = parseIntOrZero(heatReady.getAttribute("roundid"));
int heat = parseIntOrZero(heatReady.getAttribute("heat"));
cb.onHeatReady(roundid, heat, lanemask);
}
NodeList heatReadyNodes = response.getElementsByTagName("heat-ready");
if (heatReadyNodes.getLength() > 0) {
HeatReadyCallback cb = getHeatReadyCallback();
if (cb != null) {
Element heatReady = (Element) heatReadyNodes.item(0);
int lanemask = parseIntOrZero(heatReady.getAttribute("lane-mask"));
int roundid = parseIntOrZero(heatReady.getAttribute("roundid"));
int heat = parseIntOrZero(heatReady.getAttribute("heat"));
cb.onHeatReady(roundid, heat, lanemask);
}
}

if (response.getElementsByTagName("remote-start").getLength() > 0) {
RemoteStartCallback cb = getRemoteStartCallback();
if (cb != null) {
cb.remoteStart();
}
if (response.getElementsByTagName("remote-start").getLength() > 0) {
RemoteStartCallback cb = getRemoteStartCallback();
if (cb != null) {
cb.remoteStart();
}
}

if (response.getElementsByTagName("query").getLength() > 0) {
queueMessage(new Message.Flags());
}
}
}
33 changes: 33 additions & 0 deletions timer/src/org/jeffpiazza/derby/Message.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import java.io.*;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jeffpiazza.derby.devices.AllDeviceTypes;
import org.jeffpiazza.derby.devices.TimerDevice;

// TODO: Heartbeat should supply whatever ancillary information
// the timer supports (reset button pressed, lane blocked, etc.)
Expand Down Expand Up @@ -138,4 +142,33 @@ public String asParameters() {
return "message=HEARTBEAT&confirmed=" + (confirmed ? 1 : 0);
}
}

public static class Flags implements Message {
public String asParameters() {
StringBuilder sb = new StringBuilder("message=FLAGS");
try {
for (Flag flag : Flag.allFlags()) {
sb.append("&flag-").append(flag.name()).append("=");
sb.append(flag.typeName()).append(":");
sb.append(URLEncoder.encode(flag.value() == null ? "null" : flag.value().toString(), "UTF-8"));
sb.append("&desc-").append(flag.name()).append("=");
sb.append(URLEncoder.encode("" + flag.description(), "UTF-8"));
}
sb.append("&ports=");
boolean first_port = true;
for (String port : AllSerialPorts.getNames()) {
sb.append(URLEncoder.encode((first_port ? "" : ",") + port, "UTF-8"));
first_port = false;
}
for (Class<? extends TimerDevice> devclass : AllDeviceTypes.allDeviceClasses) {
sb.append("&device-").append(devclass.getSimpleName()).append("=");
sb.append(URLEncoder.encode(AllDeviceTypes.toHumanString(devclass), "UTF-8"));
}
} catch (UnsupportedEncodingException ex) { // Won't happen
return null;
}

return sb.toString();
}
}
}
1 change: 1 addition & 0 deletions timer/src/org/jeffpiazza/derby/devices/TimerTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jeffpiazza.derby.LogWriter;
import org.jeffpiazza.derby.AllSerialPorts;
import org.jeffpiazza.derby.Connector;
import org.jeffpiazza.derby.Message;
import org.jeffpiazza.derby.serialport.RecordingSerialPortWrapper;
import org.jeffpiazza.derby.serialport.SerialPortWrapper;
import org.jeffpiazza.derby.gui.TimerGui;
Expand Down
8 changes: 8 additions & 0 deletions website/ajax/action.timer-message.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require_once('inc/autoadvance.inc');
require_once('inc/replay.inc');
require_once('inc/remote-start.inc');
require_once('inc/events.inc');
require_once('inc/timer-flags.inc');

// Timer-controller-to-web-service messages:
//
Expand All @@ -32,6 +33,9 @@ require_once('inc/events.inc');
//
// message="MALFUNCTION" & detectable=0|1 & error= message
// Signals lost connection or other problem with the timer
//
// message="FLAGS" & many parameters
// Reports ports, devices, and flag settings from the timer jar

// Web-service-to-timer-controller messages:
//
Expand Down Expand Up @@ -65,6 +69,7 @@ if (have_permission(TIMER_MESSAGE_PERMISSION)) {
// timer log file (which we may well never create).
write_raceinfo("timer-log", tempnam(sys_get_temp_dir(), "timer-"));
echo "\n <success/>\n";
echo " <query/>\n";
} else if ($message == 'IDENTIFIED') {
if (isset($_POST['lane_count']) && $_POST['lane_count'] > 0) {
write_raceinfo('reported_lane_count', $_POST['lane_count']);
Expand Down Expand Up @@ -148,6 +153,9 @@ if (have_permission(TIMER_MESSAGE_PERMISSION)) {
$timer_state->set_unhealthy(isset($_POST['error']) ? $_POST['error'] : "Malfunction");
}
set_racing_state(false);
} else if ($message == 'FLAGS') {
decode_timer_flags($_POST);
echo "\n <success/>\n";
} else {
echo "\n <failure code='notunderstood'>Message "
.htmlspecialchars($message, ENT_QUOTES, 'UTF-8')
Expand Down
3 changes: 2 additions & 1 deletion website/inc/schema_version.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ function schema_version() {
}

function expected_schema_version() {
return 6;
return 7;
}

define('BALLOTING_SCHEMA', 6); // First schema version to support balloting
define('TIMER_SETTINGS_SCHEMA', 7);
?>
47 changes: 47 additions & 0 deletions website/inc/timer-flags.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php


require_once('inc/sql-script.inc');

// If we're working with an unmigrated GPRM database, we may need to create a
// kiosk table.
function create_timer_settings_table() {
run_sql_script('timer-settings');
}


function decode_timer_flags($params) {
global $db;
@create_timer_settings_table(); // Drop and recreate the table each time
foreach ($params as $p => $v) {
if (substr($p, 0, 5) == "flag-") {
$vv = explode(':', $v, 2);
read_single_value('INSERT INTO TimerSettings(kind, key, type, value)'
.' VALUES(:kind, :key, :type, :value)',
array(':kind' => 'flag',
':key' => substr($p, 5),
':type' => $vv[0],
':value' => $vv[1]));
} else if (substr($p, 0, 5) == "desc-") {
read_single_value('UPDATE TimerSettings SET description = :desc'
.' WHERE kind = :kind AND key = :key',
array(':kind' => 'flag',
':key' => substr($p, 5),
':desc' => $v));
} else if ($p == "ports") {
read_single_value('INSERT INTO TimerSettings(kind, key, value)'
.' VALUES(:kind, :key, :value)',
array(':kind' => 'ports',
':key' => $p,
':value' => $v));
} else if (substr($p, 0, 7) == "device-") {
read_single_value('INSERT INTO TimerSettings(kind, key, description)'
.' VALUES(:kind, :key, :desc)',
array(':kind' => 'device',
':key' => substr($p, 7),
':desc' => $v));
}
}
}

?>
2 changes: 2 additions & 0 deletions website/sql/access/schema.inc
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,8 @@ array(

@include_once(sql_file_path('balloting')),

@include_once(sql_file_path('timer-settings')),

array(

// --- Populate basic data
Expand Down
21 changes: 21 additions & 0 deletions website/sql/access/timer-settings.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

return array(

"DROP TABLE IF EXISTS TimerSettings",

"CREATE TABLE TimerSettings ("
." settingid COUNTER,"
." kind VARCHAR(20)," // flag, device, or ports
." key VARCHAR(100),"
." type VARCHAR(10),"
." value VARCHAR(100),"
." description VARCHAR(500),"
." pending VARCHAR(100)" // Value change requested
." )",

"CREATE UNIQUE INDEX PrimaryKey ON TimerSettings(settingid)"

);

?>
2 changes: 2 additions & 0 deletions website/sql/sqlite/schema.inc
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ make_index("Rounds", "round"),

@include_once(sql_file_path('balloting')),

@include_once(sql_file_path('timer-settings'));

array(
"INSERT INTO RaceInfo (itemkey, itemvalue) VALUES ('schema', ".expected_schema_version().")",
"INSERT INTO RaceInfo (itemkey, itemvalue) VALUES ('photos-on-now-racing', 'head')",
Expand Down
19 changes: 19 additions & 0 deletions website/sql/sqlite/timer-settings.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

return array(

"DROP TABLE IF EXISTS TimerSettings",

"CREATE TABLE TimerSettings ("
." settingid INTEGER PRIMARY KEY,"
." kind VARCHAR(20)," // flag, device, or ports
." key VARCHAR(100),"
." type VARCHAR(10),"
." value VARCHAR(100),"
." description VARCHAR(500),"
." pending VARCHAR(100)" // Value change requested
." )",

);

?>

0 comments on commit 4c7fa4c

Please sign in to comment.