/*
* Copyright (c) 2019 Clementine Computing LLC.
*
* This file is part of PopuFare.
*
* PopuFare is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PopuFare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with PopuFare. If not, see .
*
*/
var _ADDRESS = "localhost";
var _URL = "http://" + _ADDRESS;
var _PORT = 60535;
var _fqADDRESS = _ADDRESS + ":" + _PORT;
var BG_COLOR = "#f7f7f7";
var TEXT_COLOR = "#444444";
var DIU_UI_VERSION = "0.1.10";
var DIU_UI_VERSION_DATE = "2020-02-10";
var g_snd = {
"reject_fare" : "",
"accept_fare" : "",
"rule_error" : "",
"button_press" : ""
};
function _beep_error() {
g_snd.rule_error.currentTime=0;
g_snd.rule_error.play();
}
function _beep_reject() {
g_snd.reject_fare.currentTime=0;
g_snd.reject_fare.play();
}
function _beep_accept() {
g_snd.accept_fare.currentTime=0;
g_snd.accept_fare.play();
}
function _beep() {
g_snd.button_press.currentTime=0;
g_snd.button_press.play();
}
var g_ctx = {
"driver_login_state" : "driver",
"driver" : "",
"pin" : "",
"paddle" : "",
"eqnum" : "",
"cur_eqnum" : "",
"current_ui" : "ui_login",
"ui_stack" : [],
"ui_change_timeoutid": -1,
"ui_watchdog_timeoutid": -1,
"bulkfare" : "",
"bulkfare_count" : "",
"status_text": "",
"status_text_w": 32,
"status_text_h": 11,
"status_html_text":"",
"diu_status" : {},
"x": ""
};
function _api_fail() {
console.log(">>api fail");
return true;
}
function _api_tick() { }
function _api_request(action, param, cb_ok, cb_fail, cb_neterr) {
var idx = 0;
var param_name = [], param_val = [];
var req = new XMLHttpRequest();
// Firefox gets testy about parsing assumed XML
//
req.overrideMimeType("text/plain");
var url = "/req";
var varstr = "action=" + action;
for (var x in param) {
param_name.push(x);
param_val.push(param[x]);
}
for (var ii=0; ii=2) && (resp[0] == "ok")) {
if (typeof cb_ok !== "undefined") {
cb_ok(fulltxt);
}
return;
}
if (typeof cb_fail !== "undefined") {
cb_fail(fulltxt);
}
}
else if (typeof cb_fail !== "undefined") { cb_fail(); }
}
};
req.addEventListener("error", _api_fail);
req.addEventListener("abort", _api_fail);
//req.addEventListener("load", _api_tick);
//req.addEventListener("progress", _api_tick);
req.onerror = function() { console.log("network error"); };
try {
//DEBUG
console.log("req, varstr:", varstr);
req.open("POST", url, true);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.send(varstr);
} catch (er) {
console.log(">>>>>>ERROR", er);
}
}
function _block_status_window(ui_id) {
var ele = document.getElementById(ui_id + "_status");
ele.ondragstart = function() { return false; }
ele.onselectstart = function() { return false; }
ele.onmousedown = function() { return false; }
ele.ondragstart = function() { return false; }
var rect = ele.getBoundingClientRect();
var block_ele = document.getElementById(ui_id + "_blockwindow");
block_ele.style.width = rect.width;
block_ele.style.height = rect.height;
block_ele.style.bottom = rect.bottom;
block_ele.style.left = rect.left;
block_ele.style.top = rect.top;
block_ele.style.right = rect.right;
block_ele.style.x = rect.x;
block_ele.style.y = rect.y;
}
function _clear_ui_watchdog() {
if (g_ctx.ui_watchdog_timeoutid >= 0) {
window.clearTimeout(g_ctx.ui_watchdog_timeoutid);
}
}
function _set_ui_watchdog(failsafe_ui, _dt) {
// default to 'ui_watchdog' and 5s
//
failsafe_ui = (( typeof failsafe_ui === "undefined") ? "ui_watchdog" : failsafe_ui);
_dt = (( typeof _dt === "undefined") ? 5000 : _dt);
_clear_ui_watchdog();
g_ctx.ui_watchdog_timeoutid = window.setTimeout(
(function(_fsui) {
return function() { console.log("???", _fsui); _switch_ui(_fsui); };
})(failsafe_ui),
_dt);
}
function _switch_ui(to) {
var ele;
if (g_ctx.ui_change_timeoutid > 0) {
window.clearTimeout(g_ctx.ui_change_timeoutid);
g_ctx.ui_change_timeoutid = -1;
}
var from = g_ctx.current_ui;
ele = document.getElementById(from);
ele.style.display = "none";
ele = document.getElementById(to);
ele.style.display = "block";
g_ctx.current_ui = to;
if (to == "ui_main") {
var _x = _calculate_ui_main_status_width_height();
g_ctx.status_text_h = _x.n_height;
g_ctx.status_text_w = _x.n_width;
}
if ((to == "ui_main") ||
(to == "ui_login")) {
_block_status_window(to);
}
}
function _hide_ui(from) {
var ele = document.getElementById(from);
ele.style.display = "none";
}
function _hide_ui_element(from) {
var ele = document.getElementById(from);
ele.style.display = "none";
}
function _show_ui(to) {
var ele = document.getElementById(to);
ele.style.display = "block";
g_ctx.current_ui = to;
// put pane over status window to prevent highlights,
// copy/pasting, etc.
//
if ((to == "ui_main") ||
(to == "ui_login")) {
_block_status_window(to);
}
}
function _show_ui_element(to) {
var ele = document.getElementById(to);
ele.style.display = "block";
}
//------------
function _get_now_HH_MM() {
var _dt = new Date();
var _sep = ":";
if ( (_dt.getSeconds() % 2) == 0) {
_sep = " ";
}
var _hr = _dt.getHours();
var _min = _dt.getMinutes();
var _hr_str = _hr.toString();
var _min_str = _min.toString();
if (_hr < 10) { _hr_str = "0" + _hr_str; }
if (_min < 10) { _min_str = "0" + _min_str; }
var _time_str = _hr_str + _sep + _min_str;
return _time_str;
}
function _update_display_time() {
var ele = document.getElementById("ui_main_time");
if (typeof ele === "undefined") { return; }
/*
var _dt = new Date();
var _sep = ":";
if ( (_dt.getSeconds() % 2) == 0) { _sep = " "; }
var _hr = _dt.getHours();
var _min = _dt.getMinutes();
var _hr_str = _hr.toString();
var _min_str = _min.toString();
if (_hr < 10) { _hr_str = "0" + _hr_str; }
if (_min < 10) { _min_str = "0" + _min_str; }
var _time_str = _hr_str + _sep + _min_str;
*/
var _time_str = _get_now_HH_MM();
ele.innerHTML = "" + _time_str + "";
}
//------------
function _update_login_time() {
var ele = document.getElementById("ui_login_time");
if (typeof ele === "undefined") { return; }
var _time_str = _get_now_HH_MM();
ele.innerHTML = "" + _time_str + "";
}
//------------
// value is from [0,1]
//
function _process_brightness(brightness) {
// 0 opacity is completely clear, so (1.0) brightness (100% brightness).
//
var f_brightness = parseFloat(brightness);
var opacity = 1.0 - f_brightness;
// fail
//
if ((opacity < 0.0) || (opacity > 1.0)) { return {"type":"error", "msg":"opacity out of range"}; }
var ele = document.getElementById("dim_overlay");
ele.style.opacity = opacity;
ele = document.getElementById("ui_configuration_displaybrightness");
ival = Math.floor(f_brightness*100.0);
ele.innerHTML = "" + ival + "%";
}
//------------
// volume is from [0,1]
//
function _process_volume(vol) {
var ele = document.getElementById("ui_configuration_displayvolume");
ivol = Math.floor(vol*100.0);
ele.innerHTML = "" + ivol + "%";
}
function _slider_change(name) {
if (name == "configuration.volume") {
var val = document.getElementById("ui_configuration_volume").value;
_process_volume(val);
ivol = Math.floor(val*100.0);
_api_request("custom", {"function":"volume", "parameter":ivol});
}
else if (name == "configuration.brightness") {
var val = document.getElementById("ui_configuration_brightness").value;
_process_brightness(val);
}
}
function _volume_test() {
_api_request("custom", {"function":"say", "parameter":"testing 1, 2, 3"});
}
//------------
function _clear_ui_driver() {
var ele;
var u = ["driver", "pin"];
for (var i=0; i0) && (lon.length>0)) ? (" (" + lat + "/" + lon + ")") : "" );
var ele = document.getElementById("ui_login_status");
var html_a = [];
html_a.push("Tunnel: " + has_tunn + " GPRS: " + has_gprs + " Eq#: " + m["equipno"] + " #Msg: " + m["nmsg"]);
html_a.push("Last Token Read (" + m["last_token"] + ")");
html_a.push("GPS: " + has_gps + gps_str + "");
html_a.push(" ");
// some site specific fiddling to display package information
//
html_a.push(_sp("Package") + _sp("Version", "left", 18) + _sp("Installed", "right", 12));
html_a.push(_sp("ui") + _sp(DIU_UI_VERSION, "left", 18) + _sp(DIU_UI_VERSION_DATE, "right", 12) + "");
for (var _ii=0; _ii<3; _ii++) {
var key = "pkg" + _ii;
if (key in g_ctx.diu_status) {
var aval = g_ctx.diu_status[key].split(" ");
html_a.push(_sp(aval[0]) + _sp(aval[1], "left", 18) + _sp(aval[2], "right", 12));
}
}
html_a.push(" ");
if ("IMEI" in m) { html_a.push("IMEI = " + m["IMEI"] + ""); }
if ("IMSI" in m) { html_a.push("IMSI = " + m["IMSI"] + ""); }
if ("ETH0" in m) { html_a.push("ETH0 = " + m["ETH0"] + ""); }
html_a.push(" ");
for (var ii=0; ii
" + div_hdr ) + "";
ele.innerHTML = str;
}
else if (g_ctx.current_ui === "ui_main") {
var ele = document.getElementById("mainstatus");
var str = "";
str += "Rt " + m["route"] + " ";
str += "Trip " + m["trip"] + " ";
str += "Stop " + m["stop"] + " ";
str += "GPS " + m["gps"] + " ";
str += "Tun " + m["tunnel"] + ", ";
str += m["date"];
str += " " + moment().format("HH:mm");
ele.innerHTML = str;
}
}
function _cb_status_err(e) {
console.log("ERROR: _cb_status_err:", e);
}
//-------------
function _main_message_clear() {
g_ctx.status_text = "";
}
function _main_message_replace(msg, bg_color, text_color) {
var ele = document.getElementById("ui_main_status");
bg_color = ((typeof bg_color === "undefined") ? BG_COLOR : bg_color);
text_color = ((typeof text_color === "undefined") ? TEXT_COLOR : text_color);
var lines = g_ctx.status_text.split("\n");
if (lines.length > g_ctx.status_text_h) {
var n = lines.length;
lines = lines.slice(n - g_ctx.status_text_h);
}
for (var i=0; i" + html_lines[i] + "";
}
else if (html_lines[i].match(/REJECT/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/[Uu]nknown/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/[Pp]assback/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/Rule execution error/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else {
html_lines[i] = "" + html_lines[i] + "
";
}
}
g_ctx.status_text = lines.join("\n");
g_ctx.status_html_text = html_lines.join("
");
ele.innerHTML = g_ctx.status_html_text;
// sounds
//
if (msg.match(/ACCEPT/)) {
_beep_accept();
}
else if (msg.match(/REJECT/)) {
_beep_reject();
}
else if (msg.match(/[Uu]nknown/)) {
_beep_reject();
}
else if (msg.match(/[Pp]assback/)) {
_beep_reject();
}
else if (msg.match(/Rule execution error/)) {
_beep_error();
}
}
function _main_message_add(msg, bg_color, text_color) {
var ele = document.getElementById("ui_main_status");
bg_color = ((typeof bg_color === "undefined") ? BG_COLOR : bg_color);
text_color = ((typeof text_color === "undefined") ? TEXT_COLOR : text_color);
var txt = g_ctx.status_text + "\n" + msg;
var html_lines = [];
var lines = txt.split("\n");
if (lines.length > g_ctx.status_text_h) {
var n = lines.length;
lines = lines.slice(n - g_ctx.status_text_h);
}
for (var i=0; i" + html_lines[i] + "";
}
else if (html_lines[i].match(/REJECT/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/[Uu]nknown/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/[Pp]assback/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else if (html_lines[i].match(/Rule execution error/)) {
html_lines[i] = "" + html_lines[i] + "
";
}
else {
html_lines[i] = "" + html_lines[i] + "
";
}
}
g_ctx.status_text = lines.join("\n");
g_ctx.status_html_text = html_lines.join("
");
ele.innerHTML = g_ctx.status_html_text;
// sounds
//
if (msg.match(/ACCEPT/)) {
_beep_accept();
}
else if (msg.match(/REJECT/)) {
_beep_reject();
}
else if (msg.match(/[Uu]nknown/)) {
_beep_reject();
}
else if (msg.match(/[Pp]assback/)) {
_beep_reject();
}
else if (msg.match(/Rule execution error/)) {
_beep_error();
}
}
//-------------
//-------------
//-------------
function _ws_process(dat) {
console.log("_ws_process:", dat);
var tok = dat.split(" ");
if (tok.length < 2) { return; }
if (tok[0] == "paddle") {
if (tok[1] == "ok") { _verify_paddle_ok(); }
else if (tok[1] == "fail") { _verify_paddle_fail(); }
else { _verify_paddle_fail(); }
}
else if (tok[0] == "driver_notify") {
if (tok.length < 5) {
console.log("malformed message: ", dat);
}
else if (tok[1] == "replace") {
_main_message_replace(tok.slice(4).join(" "));
}
else if (tok[1] == "ok") {
_main_message_add(tok.slice(4).join(" "));
}
else {
console.log("unknown message: ", dat);
}
}
}
function _init_websocket() {
var sock = new WebSocket("ws://" + _fqADDRESS);
sock.onopen = function(e) { console.log("open", e); }
sock.onmessage = function(e) { _ws_process(e.data); }
sock.onclose = function(e) {
console.log("close", e);
setTimeout( function() { _init_websocket(); }, 1000);
}
sock.onerror = function(e) {
console.log("error", e);
}
}
//-------------
var ui_pattern = {
"state" : "idle",
"lastX" : 0,
"lastY" : 0,
"curX" : 0,
"curY" : 0
};
function ui_pattern_mousedown(ev) {
var ele = document.getElementById("body");
var rect = ele.getBoundingClientRect();
var x = ev["x"];
var y = ev["y"];
var width = rect.width;
var height = rect.height;
if (ui_pattern.state == "idle") {
if (y < (height/4)) {
ui_pattern.state = "square_0";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_0") {
if (x > (3*width/4)) {
ui_pattern.state = "square_1";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_1") {
if (y > (3*height/4)) {
ui_pattern.state = "square_2";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_2") {
if (x < (width/4)) {
ui_pattern.state = "square_3";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_3") {
if (y < (height/4)) {
ui_pattern.state = "square_4";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_4") {
if (x > (3*width/4)) {
ui_pattern.state = "square_5";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_5") {
if (y > (3*height/4)) {
ui_pattern.state = "square_6";
}
else {
ui_pattern.state = "idle"
}
}
else if (ui_pattern.state == "square_6") {
if (x < (width/4)) {
_switch_ui("ui_diagnostic");
}
ui_pattern.state = "idle"
}
return false;
}
function ui_pattern_mouseup(ev) {
return false;
}
//------------
function _mainscreen() {
_switch_ui('ui_login');
g_ctx.driver_login_state = "driver";
_clear_ui_driver();
_clear_ui_paddle();
}
function _configuration() {
_switch_ui('ui_configuration');
g_ctx.driver_login_state = "driver";
_clear_ui_driver();
_clear_ui_paddle();
}
function _configuration_back() {
var ui_prev = "ui_login";
if (g_ctx.ui_stack.length > 0) {
ui_prev = g_ctx.ui_stack.pop();
}
_switch_ui(ui_prev);
if (ui_prev == "ui_login") {
g_ctx.driver_login_state = "driver";
_clear_ui_driver();
_clear_ui_paddle();
}
}
function _eqnum() {
_switch_ui('ui_eqnum');
g_ctx.driver_login_state = "driver";
if (g_ctx.cur_eqnum.length > 0) {
var ele = document.getElementById("ui_eqnum_eqnum");
ele.innerHTML = g_ctx.cur_eqnum;
g_ctx.eqnum = g_ctx.cur_eqnum;
}
_clear_ui_driver();
_clear_ui_paddle();
}
function _reset() {
_switch_ui('ui_login');
g_ctx.driver_login_state = "driver";
_clear_ui_driver();
_clear_ui_paddle();
location.reload(true);
}
function _reboot() {
_api_request("custom", {"function":"reboot"});
_switch_ui('ui_login');
g_ctx.driver_login_state = "driver";
_clear_ui_driver();
_clear_ui_paddle();
}
function _custom0() {
_api_request("interfaceupdown", {"interface":"eth0", "state":"up"});
}
function _custom1() {
_api_request("interfaceupdown", {"interface":"eth0", "state":"down"});
}
function _update_diagnostic_window(_msg) {
var ele = document.getElementById("ui_diagnostic_view");
ele.innerHTML = _msg;
}
function _custom2() {
_api_request("interfaceinfo", {"interface":"eth0"}, _update_diagnostic_window);
}
function _custom3() {
_api_request("say", {"message":"speech test"});
}
function _custom4() {
}
function _custom5() {
}
//------------
function _set_eqnum() {
if (g_ctx.eqnum.length == 0) { return; }
_api_request("eqnum", {"eqnum":g_ctx.eqnum}, function(inp) { console.log("eqnum ok:", inp); }, function(inp) { console.log("eqnum error:", inp); });
}
function _eqnum_input(inp) {
var n = g_ctx.eqnum.length;
if (inp == 'cancel') { _switch_ui('ui_login'); }
else if (inp == 'ok') {
_set_eqnum();
_switch_ui('ui_login');
return;
}
else if (inp == 'bksp') { g_ctx.eqnum = g_ctx.eqnum.substr(0, n-1); }
else if (inp == 'clr') { g_ctx.eqnum = ""; }
else { g_ctx.eqnum += inp; }
// Otherwise update the displayed equipment number
//
var ele = document.getElementById('ui_eqnum_eqnum');
ele.innerHTML = g_ctx.eqnum;
}
//-------------
function _text_width_height() {
var _t = document.getElementById("ui_test");
console.log(">>>", _t.clientHeight, _t.clientWidth);
}
function _calculate_ui_main_status_width_height() {
var _t = document.getElementById("ui_test");
var ch_w = _t.clientWidth;
var ch_h = _t.clientHeight;
var _w = document.getElementById("ui_main_status");
var win_w = _w.clientWidth;
var win_h = _w.clientHeight;
var n_w = Math.floor(win_w / ch_w);
var n_h = Math.floor(win_h / ch_h);
return {"n_width": n_w, "n_height":n_h};
}
function _init_dim_overlay() {
var ele = document.getElementById("ui_dim_overlay");
}
function init() {
_init_websocket();
_init_dim_overlay();
window.setInterval(_update_display_time, 200);
window.setInterval(_update_login_time, 200);
// watchdog
//
document.getElementById('ui_watchdog_btn').onclick = _watchdog_tripped;
// diagnostics
//
document.getElementById('ui_diagnostic_mainscreen').onclick = _mainscreen;
document.getElementById('ui_diagnostic_reset').onclick = _reset;
document.getElementById('ui_diagnostic_reboot').onclick = _reboot;
document.getElementById('ui_diagnostic_custom0').onclick = _custom0;
document.getElementById('ui_diagnostic_custom1').onclick = _custom1;
document.getElementById('ui_diagnostic_custom2').onclick = _custom2;
document.getElementById('ui_diagnostic_custom3').onclick = _custom3;
document.getElementById('ui_diagnostic_custom4').onclick = _custom4;
document.getElementById('ui_diagnostic_custom5').onclick = _custom5;
// configuration
//
//document.getElementById('ui_configuration_back').onclick = _mainscreen;
document.getElementById('ui_configuration_back').onclick = _configuration_back;
document.getElementById('ui_configuration_volumetest').onclick = _volume_test;
document.getElementById('ui_configuration_eqnum').onclick = _eqnum;
// equipment number change
//
document.getElementById('ui_eqnum_cancel').onclick = _mainscreen;
document.getElementById('ui_eqnum_ok').onclick = function() { console.log("eqnum change"); }
// login
//
document.getElementById('ui_login_login').onclick = _login;
document.getElementById('ui_login_configuration').onclick = _configuration;
document.getElementById('ui_driverincorrect_btn').onclick = _driver_incorrect;
document.getElementById('ui_paddleunknown_btn').onclick = _paddle_unknown;
// main menu buttons
//
document.getElementById('ui_main_prv').onclick = _main_prv;
document.getElementById('ui_main_nxt').onclick = _main_nxt;
document.getElementById('ui_main_bulk').onclick = _main_bulk;
document.getElementById('ui_main_menu').onclick = _main_menu;
document.getElementById('ui_main_dim').onclick = _main_dim;
// dim
//
document.getElementById('ui_dim_btn').onclick = _dim_wakeup;
var simple_fares = [ "adult", "youth", "half", "bike", "wheelchair", "transfer"];
var simple_fares_f = [ _fare_adult, _fare_youth, _fare_half, _fare_bike, _fare_wheelchair, _fare_transfer];
for (var ii=0; ii 0)) {
bulk_pass = BULK_PASS;
}
if ((typeof BULK_RULE !== "undefined") && (BULK_RULE.length > 0)) {
bulk_rule= BULK_RULE;
}
if ((typeof BULK_PASS_NAME !== "undefined") && (BULK_PASS_NAME.length > 0)) {
bulk_pass_name = BULK_PASS_NAME;
}
for (var i=0; i 0)) {
override_pass = OVERRIDE_PASS;
}
if ((typeof OVERRIDE_RULE !== "undefined") && (OVERRIDE_RULE.length > 0)) {
override_rule= OVERRIDE_RULE;
}
for (var i=0; i