Last active
August 29, 2015 14:00
-
-
Save blindman2k/11305787 to your computer and use it in GitHub Desktop.
Imp gateway demo - communicate with a line-oriented UART device through a web interface
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
const HTML = @" | |
<!DOCTYPE html> | |
<html lang='en'> | |
<head> | |
<meta charset='utf-8'> | |
<meta http-equiv='X-UA-Compatible' content='IE=edge'> | |
<meta name='viewport' content='width=device-width, initial-scale=1'> | |
<title>Imp Gateway Demo</title> | |
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.min.css'> | |
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap-theme.min.css'> | |
</head> | |
<body> | |
<div class='container col-xs-12 col-sm-10 col-sm-offset-1' > | |
<div class='well' style='margin-top: 25px;'> | |
<h1 style='margin-top:0px;'>Imp Gateway Demo</h1> | |
<form role='form' style='margin-top: 25px;'> | |
<div class='form-group'> | |
<label for='url'>URL</label> | |
<input id='url' type='text' class='form-control' placeholder='http://requestb.in/1gni9ar1'> | |
<div class='text-right'> | |
<button id='configure' class='btn btn-primary btn-large' style='margin-top:15px;'>Config</button> | |
</div> | |
</div> | |
<div class='form-group' style='margin-top: 15px;'> | |
<label for='command'>COMMAND</label> | |
<textarea id='command' class='form-control' rows='3'></textarea> | |
</div> | |
<div class='text-right'> | |
<button id='post' class='btn btn-primary btn-large' style='margin-top:15px;'>Post</button> | |
</div> | |
</form> | |
</div> | |
<div class='well' style='margin-top: 25px;'> | |
<h1 style='margin-top:0px;'>Log</h1> | |
<p id='debugs'></p> | |
<div class='text-right'> | |
<button id='clear' class='btn btn-primary btn-large' style='margin-top:15px;'>Clear</button> | |
</div> | |
</div> | |
</div> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js'></script> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/js/bootstrap.min.js'></script> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery-dateFormat/1.0/jquery.dateFormat.min.js'></script> | |
<script> | |
$(function() { | |
$('#url').val('%s'); | |
$('#configure').click(function() { | |
$.ajax({ | |
type: 'POST', | |
url: window.location.pathname + '/config', | |
data: { url : $('#url').val() } | |
}); | |
return false; | |
}) | |
$('#post').click(function() { | |
if ($('#command').val() != '') { | |
$.ajax({ | |
type: 'POST', | |
url: window.location.pathname, | |
data: $('#command').val() | |
}); | |
} | |
return false; | |
}) | |
$('#clear').click(function() { | |
$.ajax({ | |
type: 'GET', | |
url: window.location.pathname + '/clear', | |
success: function(data) { | |
$('#debugs').html(''); | |
} | |
}); | |
return false; | |
}) | |
function getlogs() { | |
$.ajax({ | |
type: 'GET', | |
url: window.location.pathname + '/logs', | |
timeout: 4500, | |
success: function(data) { | |
$('#debugs').html(''); | |
data.forEach(function(log) { | |
var d = new Date(); | |
d.setTime(log.ts * 1000); | |
var ts = jQuery.format.toBrowserTimeZone(d, 'yyyy-MM-dd HH:mm:ss'); | |
ts = ts.replace(/ /g, ' '); | |
ts = ts.replace(/-/g, '‑'); | |
var text = $('<p>').text(log.text).html(); | |
var line = '<span style=""font-family:monospace;"">' + ts + '<code>[' + log.type + ']</code> ' + text + '</span>'; | |
$('#debugs').prepend(line + '<br/>'); | |
}) | |
} | |
}); | |
} | |
setInterval(getlogs, 5000); | |
getlogs(); | |
}) | |
</script> | |
</body> | |
</html> | |
"; | |
// ----------------------------------------------------------------------------- | |
class Gateway_Agent { | |
_callbacks = null; | |
_debugs = null; | |
_url = null; | |
_persist = null; | |
// ......................................................................... | |
constructor(persist = null) { | |
const MAXIMUM_DEBUGS = 20; | |
_callbacks = {}; | |
_persist = persist; | |
_debugs = _persist ? _persist.read("debugs", []) : []; | |
_url = _persist ? _persist.read("url", "") : ""; | |
device.on("line", device_read.bindenv(this)); | |
http.onrequest(http_request.bindenv(this)) | |
on("json", post_json.bindenv(this)); | |
on("debug", post_debug.bindenv(this)); | |
} | |
// ......................................................................... | |
function device_read(line) { | |
local json; | |
try { | |
json = http.jsondecode(line); | |
} catch (e) { | |
if ("debug" in _callbacks) _callbacks["debug"](line); | |
return; | |
} | |
if ("json" in _callbacks) _callbacks["json"](json); | |
} | |
// ......................................................................... | |
function http_request(req, res) { | |
try { | |
if (req.method == "POST") { | |
if (req.path == "/config") { | |
// This is the update of configuration data | |
try { | |
local config = http.urldecode(req.body); | |
if ("url" in config && config.url != "") { | |
_url = config.url; | |
if (_persist) _persist.write("url", _url); | |
} | |
} catch (e) { | |
res.send(400, "Invalid configuration data"); | |
return; | |
} | |
res.send(200, "OK"); | |
} else { | |
// This is the POSTing of a data block | |
local line = null; | |
try { | |
line = http.jsonencode(http.jsondecode(req.body)); | |
post_debug(line, "*->") | |
} catch (e) { | |
line = req.body; | |
post_debug(line, "-->") | |
} | |
device.send("send", line); | |
res.send(200, "OK"); | |
} | |
} else if (req.path == "/clear") { | |
_debugs = []; | |
if (_persist) _persist.remove("debugs"); | |
res.send(200, "OK"); | |
} else if (req.path == "/logs") { | |
res.header("Content-Type", "application/json"); | |
res.send(200, http.jsonencode(_debugs)); | |
} else { | |
// Anything else, send the HTML | |
res.send(200, format(HTML, _url)); | |
} | |
} catch (e) { | |
server.error(e) | |
res.send(500, "Exception: " + e); | |
} | |
} | |
// ......................................................................... | |
function post_json(json) { | |
post_debug(http.jsonencode(json), "<-*") | |
local url = _url; | |
if ("data" in json && "url" in json.data) url = json.data.url; | |
if (url) { | |
local headers = { "Content-Type": "application/json" }; | |
local body = http.jsonencode(json); | |
local req = http.post(url, headers, body); | |
req.sendasync(function(res) { | |
if (res.statuscode != 200) { | |
server.error("Error " + res.statuscode + " posting JSON to " + url); | |
} | |
}); | |
} else { | |
server.log("No URL to POST the JSON to: " + http.jsonencode(json)) | |
} | |
} | |
// ......................................................................... | |
function post_debug(debug, type = "<--") { | |
_debugs.push( { ts = time(), text = debug, type = type } ); | |
if (_debugs.len() > MAXIMUM_DEBUGS) _debugs.remove(0); | |
if (_persist) _persist.write("debugs", _debugs); | |
} | |
// ......................................................................... | |
function on(event, callback) { | |
if (callback == null) { | |
delete _callbacks[event]; | |
} else { | |
_callbacks[event] <- callback; | |
} | |
} | |
} | |
// ----------------------------------------------------------------------------- | |
class Persist { | |
cache = null; | |
// ------------------------------------------------------------------------- | |
function read(key = null, def = null) { | |
if (cache == null) { | |
cache = server.load(); | |
} | |
return (key in cache) ? cache[key] : def; | |
} | |
// ------------------------------------------------------------------------- | |
function write(key, value) { | |
if (cache == null) { | |
cache = server.load(); | |
} | |
if (key in cache) { | |
server.save(cache); | |
} else { | |
cache[key] <- value; | |
server.save(cache); | |
} | |
return value; | |
} | |
// ------------------------------------------------------------------------- | |
function remove(key) { | |
if (cache == null) { | |
cache = server.load(); | |
} | |
if (key in cache) { | |
delete cache[key]; | |
server.save(cache); | |
} | |
} | |
} | |
// ----------------------------------------------------------------------------- | |
persist <- Persist(); | |
gateway <- Gateway_Agent(persist); | |
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
// ----------------------------------------------------------------------------- | |
class Gateway_Device { | |
_uart = null; | |
_uart_buffer = null; | |
_callbacks = null; | |
// ......................................................................... | |
constructor(uart) { | |
_uart = uart; | |
_uart_buffer = ""; | |
_callbacks = {}; | |
_uart.configure(115200, 8, PARITY_NONE, 1, 0, uart_read.bindenv(this)) | |
agent.on("send", agent_data.bindenv(this)) | |
on("line", send_data.bindenv(this)); | |
} | |
// ......................................................................... | |
function uart_read() { | |
local ch; | |
while ((ch = _uart.read()) != -1) { | |
if (ch == '\r' || ch == '\n') { | |
if (_uart_buffer.len() > 0 && "line" in _callbacks) { | |
_callbacks["line"](_uart_buffer); | |
} | |
_uart_buffer = ""; | |
} else { | |
_uart_buffer += ch.tochar(); | |
} | |
} | |
} | |
// ......................................................................... | |
function agent_data(data) { | |
_uart.write(data + "\r\n"); | |
} | |
// ......................................................................... | |
function send_data(line) { | |
agent.send("line", line); | |
} | |
// ......................................................................... | |
function on(event, callback) { | |
if (callback == null) { | |
delete _callbacks[event]; | |
} else { | |
_callbacks[event] <- callback; | |
} | |
} | |
} | |
// ----------------------------------------------------------------------------- | |
gateway <- Gateway_Device(hardware.uart57); | |
gateway.agent_data("Device rebooted"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment