-
-
Save hfiennes/07d5f8f53ed4e11d44b02071e9963c48 to your computer and use it in GitHub Desktop.
A time experiment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Latency history | |
const SAMPLES = 10 | |
rtt_history <- []; | |
// Send a timestamp packet to the imp, which it will loop back | |
// Comapring the times when we get the return tells us the RTT | |
function link_latency() { | |
local d = date(); | |
device.send("latency", { "s":d.time, "us":d.usec }); | |
} | |
// Process the returned time packet | |
device.on("latency", function(v) { | |
// Get the agent's view of the current time | |
local d = date(); | |
// Work out the RTT, and push it into the history array | |
local rtt = 1000000*(d.time - v.s) + (d.usec - v.us); | |
rtt_history.push(rtt); | |
// Did we get enough of them? | |
if (rtt_history.len() == SAMPLES) { | |
// Calculate mean | |
local total = rtt_history.reduce(function(p,c) { return p+c; }); | |
local mean = 1.0*total / rtt_history.len(); | |
// Calculate squared differences from mean, sum them, then take square root to get stddev | |
local sqdiff = rtt_history.map(function(d) { return (d-mean)*(d-mean); }); | |
local sqdiff_total = sqdiff.reduce(function(p,c) { return p+c; }); | |
local sqdiff_mean = sqdiff_total / sqdiff.len(); | |
local stddev = math.sqrt(sqdiff_mean); | |
//server.log("mean="+mean+"us, stddev="+stddev+"us"); | |
// Does this look okish, using a totally arbitrary bar? | |
if (stddev > (mean*0.1)) { | |
// Looks a bit high, so we'll start another cycle | |
//server.log("deviation too high, trying again"); | |
measure_rtt(); | |
} else { | |
// Looks ok, let's use this. We halve it as we are just interested in | |
// time time it takes for the packet to arrive at the client | |
send_corrected_time(mean / 2); | |
} | |
} else { | |
// Send another packet | |
link_latency(); | |
} | |
}); | |
// Kick of RTT measurement cycle | |
function measure_rtt() { | |
rtt_history = []; | |
link_latency(); | |
} | |
// Now we have an RTT offset, send it to the device | |
// Note! offset_us must be an integer, otherwise you get float promotion and | |
// things are strangely bad | |
function send_corrected_time(offset_us) { | |
// Get agent time | |
local d = date(); | |
// By the time this arrives with the client, it'll be on average offset_us old, | |
// so add this to the time we're sending | |
d.usec += offset_us.tointeger(); | |
d.time += (d.usec / 1000000); | |
d.usec = d.usec % 1000000; | |
device.send("time", { "s":d.time, "us":d.usec }); | |
} | |
// Send corrections every 10s | |
function repeat() { | |
measure_rtt(); | |
imp.wakeup(10, repeat); | |
} | |
// Wait for device to be ready after a build & run | |
imp.wakeup(1, function() { repeat(); }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Respond to an RTT request by returning the packet | |
agent.on("latency", function(v) { agent.send("latency", v); }); | |
// In order to be able to return a "more accurate" time, we need to store the | |
// accurate time and when we received it from the server | |
reference_time <- { "s":0, "us":0 }; | |
reference_received <- 0; | |
// Deal with a corrected time sent from the agent | |
agent.on("time", function(v) { | |
// Set these as references | |
local now = hardware.millis(); | |
// For this demo, save what our local concept of "accurate time" is | |
local pre_sync = get_time(); | |
// Now, update the reference | |
reference_time = v; | |
reference_received = now; | |
// Now get our *new* concept of "accurate time" | |
local post_sync = get_time(); | |
// ...and get diff & log it | |
local diff = 1000000*(post_sync.s - pre_sync.s) + (post_sync.us - pre_sync.us); | |
server.log(format("pre %d.%06d -> post %d.%06d, diff %dus", | |
pre_sync.s, pre_sync.us, | |
post_sync.s, post_sync.us, | |
diff)); | |
}); | |
// Return the "accurised" time ;) | |
function get_time() { | |
// Work out time since last server fix | |
local since = hardware.millis() - reference_received; | |
// Add to reference & normalize | |
local r = { "s": reference_time.s, "us": reference_time.us }; | |
r.us += (since * 1000); | |
r.s += r.us / 1000000; | |
r.us = r.us % 1000000; | |
return r; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment