Browse Source

wip

* updating DIU bus unit server. Currently in active development
clementinecomputing 6 years ago
parent
commit
1f7cd0eec7

+ 19 - 0
busunit/DIU/diu_main.c

@@ -645,6 +645,20 @@ int main(int argc, char **argv)
     clear_diu_messages();
     
 
+    // This is the main dispatch loop:
+    //
+    // * reset watchdog to make sure we haven't crashed/frozen
+    // * if need be, open a connection to the DIU microcontroller, quieting all messages except for acks
+    // * handle GPS message dispatch through IPC
+    // * if need be, handle reload of menu.xml
+    // * manage driver status message communication
+    // * handle paddle change
+    // * draw menu
+    // * listen on the mailboxes for messages and process. This includes
+    //   - touchscreen events
+    //   - gps updates
+    //   - warning/debug/error messages
+    //
     while( exit_request_status == EXIT_REQUEST_NONE )	//loop until we get asked to exit...
     {
 
@@ -795,6 +809,11 @@ int main(int argc, char **argv)
             fds[nfd].revents = 0;
             nfd++;
         }
+
+        for (int i=0; i<nfd; i++) {
+          printf("[%i] %i\n", i, (int)fds[nfd].fd);
+        }
+        printf("\n\n");
     
         if(nfd > 0)	//if we have any file descriptors, poll them
         {

+ 86 - 0
busunit/DIU/diuhttpd/diuhttp.c

@@ -3,11 +3,25 @@
 //
 #include "mongoose.h"
 
+#include <sys/time.h>
+
 #define _SLEN 1024
 
 static const char *s_http_port = "60535";
 static struct mg_serve_http_opts s_http_server_opts;
 
+static int is_websocket(const struct mg_connection *nc) {
+  return nc->flags & MG_F_IS_WEBSOCKET;
+}
+
+long long int _get_usec_time() {
+  struct timeval tv;
+  gettimeofday(&tv,NULL);
+  return (long long int)tv.tv_usec + (1000000 * (long long int)tv.tv_sec);
+}
+
+
+//
 // ui wants status information
 //
 static void handle_status_input(struct mg_connection *nc, struct http_message *hm) {
@@ -30,11 +44,13 @@ static void handle_status_input(struct mg_connection *nc, struct http_message *h
       "310260877138191",
       "00:80:66:10:E8:8A");
 
+  /*
   printf(">> status:\nbuf(%i):\n%s\n", (int)strlen(buf), buf);
 
   //snprintf(buf, _SLEN, "ok xxx=foo bar;yyy=baz qux;...");
 
   printf(">> status\n");
+  */
 
   mg_printf(nc, "HTTP/1.1 200 OK\r\nContent-Length: %lu\r\n\r\n%s",
       (unsigned long)strlen(buf), buf);
@@ -233,6 +249,18 @@ static void handle_req(struct mg_connection *nc, struct http_message *hm) {
 
 }
 
+static void process_ws_message(struct websocket_message *ws_msg) {
+  int i;
+  char *data;
+
+  data = (char *)(ws_msg->data);
+  printf("#ws, got(%i)\n:", (int)(ws_msg->size));
+  for (i=0; i<ws_msg->size; i++) {
+    printf("%c", data[i]);
+  }
+  printf("\n");
+}
+
 static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
   struct http_message *hm = (struct http_message *) ev_data;
 
@@ -247,6 +275,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
   }
 
   switch (ev){
+
     case MG_EV_HTTP_REQUEST:
       if (mg_vcmp(&hm->uri, "/req")==0) {
         handle_req(nc, (struct http_message *)ev_data);
@@ -255,6 +284,20 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
         mg_serve_http(nc, (struct http_message *) ev_data, s_http_server_opts);
       }
       break;
+
+    case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
+      printf("ws handshake done\n");
+      break;
+    case MG_EV_WEBSOCKET_FRAME:
+      process_ws_message((struct websocket_message *)ev_data);
+      break;
+
+    case MG_EV_CLOSE:
+      if (is_websocket(nc)) {
+        printf("ws closed\n");
+      }
+      break;
+
     default:
       //printf("? %i\n", ev);
       break;
@@ -262,9 +305,43 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
 
 }
 
+static void foo(struct mg_mgr *mgr) {
+  int n;
+  char buf[_SLEN];
+  struct mg_connection *c;
+
+  for (c=mg_next(mgr, NULL); c ; c = mg_next(mgr, c)) {
+    printf("...\n");
+
+    snprintf(buf, _SLEN, "hello");
+    n = strlen(buf);
+    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, n);
+  }
+
+}
+
+static void send_ws_heartbeat(struct mg_connection *nc) {
+  int n;
+  char buf[_SLEN];
+  struct mg_connection *c;
+
+  for (c=mg_next(nc->mgr, NULL); c ; c = mg_next(nc->mgr, c)) {
+    if (c==nc) { continue; }
+    if (!is_websocket(c)) { continue; }
+    printf("...\n");
+
+    snprintf(buf, _SLEN, "hello");
+    n = strlen(buf);
+    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, n);
+  }
+
+}
+
 int main(void) {
   struct mg_mgr mgr;
   struct mg_connection *nc;
+  struct timeval tv_now, tv_prv;
+	long long int _tnow, _tprv;
 
   mg_mgr_init(&mgr, NULL);
   printf("Starting web server on port %s\n", s_http_port);
@@ -279,8 +356,17 @@ int main(void) {
   s_http_server_opts.document_root = "html";
   s_http_server_opts.enable_directory_listing = "no";
 
+  _tprv = _get_usec_time();
+
   for (;;) {
     mg_mgr_poll(&mgr, 1000);
+
+    _tnow = _get_usec_time();
+    if ((_tnow - _tprv) > 1000) {
+      send_ws_heartbeat(nc);
+      _tprv = _tnow;
+    }
+    //foo(&mgr);
   }
   mg_mgr_free(&mgr);
 

+ 2 - 1
busunit/DIU/diuhttpd/html/js/diu_ui-ORG.js

@@ -32,7 +32,8 @@ function _api_request(action, param, cb_ok, cb_fail, cb_neterr) {
   var param_name = [], param_val = [];
 
   var req = new XMLHttpRequest();
-  var url = _URL + ":" + _PORT + "/req";
+  //var url = _URL + ":" + _PORT + "/req";
+  var url =  "/req";
   var varstr = "action=" + action;
 
   for (var x in param) {

+ 6 - 0
busunit/DIUv2/buildit.sh

@@ -0,0 +1,6 @@
+#!/bin/sh
+
+common_stuff="../commhub/commhub.c ../commhub/client_utils.c ../common/common_defs.c"
+
+rm -f diu_minder
+$target_cc $target_ccopts -o diu_minder -lcrypto diu_main.c touchscreen.c driver.c mongoose.c mkgmtime.c $common_stuff

+ 8 - 0
busunit/DIUv2/buildit_native.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+target="native"
+
+. ../configure_target.sh.include
+
+./buildit.sh
+

+ 8 - 0
busunit/DIUv2/buildit_viper.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+
+target="viper"
+
+. ../configure_target.sh.include
+
+./buildit.sh
+

File diff suppressed because it is too large
+ 1479 - 0
busunit/DIUv2/diu_main.c


+ 191 - 0
busunit/DIUv2/driver.c

@@ -0,0 +1,191 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "driver.h"
+
+//This function searches the driver file and checks a driver, pin pair returning 0 on success
+//or -1 on failure.
+int driver_login(int drivernum, char *pinnum)
+{
+    FILE *f;
+    char name[DRIVER_NAME_LEN]={0};
+    char pin[64];
+    char line[LINE_BUFFER_SIZE]={0};
+    char *inc_line;
+    struct message_record outgoing_msg;
+
+
+    int drv;
+    int retval;
+
+    if(!drivernum || !pinnum) { return -1; }
+
+    f=fopen(DRIVERS_FILE,"rb");       //open the driver file
+
+    if(!f)
+    {
+        format_log_message(&outgoing_msg, LOGLEVEL_ERROR, "Cannot open %s\n", DRIVERS_FILE);
+        send_message(hub_fd,&outgoing_msg);
+        return -1;            //fail if we can't read it
+    }
+
+    while(!feof(f))         //while we haven't hit EOF
+    {
+        if(!fgets(line,sizeof(line)-1,f))   //read it line by line
+            break;
+
+        line[sizeof(line)-1] = '\0';          //terminating each line safely
+    
+        inc_line = line;
+
+        while(1)        //and ignoring any leading whitespace
+        {
+            char c = *inc_line;
+
+            if( (c == ' ') ||(c == '\t') ||(c == '\r') ||(c == '\n') )
+            {
+                inc_line++;
+                continue;
+            }
+ 
+            break;
+        }
+
+        if( (inc_line[0] == '#') || (inc_line[0] == '\0'))                      //and ignoring blank/comment lines
+            continue;
+    
+        name[0]='\0';
+        pin[0]='\0';        
+ 
+        retval=sscanf(inc_line,"%d %63[0123456789] %63[^\r\n]",&drv,pin,name);  //parse the line format (drivernum pin_num drivername)
+
+        if(retval >= 2)           //if we get at least a driver number and pin number
+        {
+            if(drv != drivernum)          //check to see if we've found a match
+                continue;
+
+            if(!strcmp(pinnum, pin))    //if the PIN matches
+            {
+                my_driver_status.logged_in_driver = drivernum;
+                strncpy(my_driver_status.driver_name, name, DRIVER_NAME_LEN);
+                my_driver_status.driver_name[DRIVER_NAME_LEN - 1] = '\0';
+                my_driver_status.equip_num = get_equip_num();
+ 
+                format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Successful login for driver %d\n", drivernum);
+                send_message(hub_fd,&outgoing_msg);
+
+                update_driver_status |= 1;
+                fclose(f);
+                return 0; 
+            }
+            else
+            {
+                format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed login for driver %d\n", drivernum);
+                send_message(hub_fd,&outgoing_msg);
+                fclose(f);
+                return -1;
+            }      
+        }
+    }
+    
+    format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed login for unknown driver %d\n", drivernum);
+    send_message(hub_fd,&outgoing_msg);
+    fclose(f); 
+    return -1;
+}
+
+//Log a driver out and cancel any pending set paddle request
+int driver_logout()
+{    
+    struct message_record outgoing_msg;
+        
+    if(my_driver_status.logged_in_driver)
+    {
+        format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Driver logout for driver %d\n", my_driver_status.logged_in_driver);
+        send_message(hub_fd,&outgoing_msg);
+    }
+     
+    my_driver_status.logged_in_driver = 0;
+    my_driver_status.driver_name[0] = '\0';
+    paddle_req_timeout = 0;
+    update_driver_status |= 1;
+    return 0;   
+}           
+ 
+int make_paddle_request(int paddle, char *okmenu, char *failmenu)
+{
+    struct message_record outgoing_msg;
+
+    paddle_req.result = 0;
+    paddle_req.request = paddle;
+    paddle_req_timeout = time(NULL) + PADDLE_REQ_TIMEOUT;
+
+    //paddle_ok_menu = okmenu;
+    //paddle_fail_menu = failmenu;
+
+    prepare_message(&outgoing_msg, MAILBOX_SET_PADDLE, &paddle_req, sizeof(paddle_req));
+    return send_message(hub_fd, &outgoing_msg);
+}
+
+//int check_paddle_request(menutree *mt)
+int check_paddle_request()
+{
+    struct message_record outgoing_msg;
+
+    if(paddle_req_timeout != 0)
+    {
+
+        if(paddle_req.request == paddle_req.result)
+        {
+            format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Set Paddle %d\n", paddle_req.request);
+            send_message(hub_fd, &outgoing_msg);
+            paddle_req_timeout = 0;
+            //setmenu(mt, paddle_ok_menu);
+            return 1;
+        }
+        else if( (paddle_req.result < 0) || (paddle_req_timeout < time(NULL)) )
+        {
+            format_log_message(&outgoing_msg, LOGLEVEL_DEBUG, "Failed to set Paddle %d\n", paddle_req.request);
+            send_message(hub_fd, &outgoing_msg);
+            paddle_req.result = 0;
+            paddle_req.request = 0;
+            paddle_req_timeout = 0;
+            //setmenu(mt, paddle_fail_menu);
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+void action_nextstop()
+{
+    struct message_record outgoing_msg;
+    prepare_message(&outgoing_msg, MAILBOX_NEXT_STOP, "", 0);
+    send_message(hub_fd, &outgoing_msg);
+}
+
+void action_prevstop()
+{
+    struct message_record outgoing_msg;
+    prepare_message(&outgoing_msg, MAILBOX_PREV_STOP, "", 0);
+    send_message(hub_fd, &outgoing_msg);
+}
+

+ 50 - 0
busunit/DIUv2/driver.h

@@ -0,0 +1,50 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _DRIVER_H
+#define _DRIVER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <string.h>
+
+#include "../commhub/commhub.h"
+#include "../commhub/client_utils.h"
+#include "../common/common_defs.h"
+
+extern driver_status my_driver_status;
+extern int update_driver_status;
+
+extern time_t paddle_req_timeout;
+extern set_paddle_req paddle_req;
+
+extern int hub_fd;
+
+//-------------------------------------------------------------------------------------
+
+void clear_diu_messages();
+int check_paddle_request();
+
+#endif

+ 2 - 0
busunit/DIUv2/drivers.txt

@@ -0,0 +1,2 @@
+00078	00078	Foo Bar
+4111	4111	AdminMode

+ 343 - 0
busunit/DIUv2/html/css/diustyles.css

@@ -0,0 +1,343 @@
+html, body {
+  height: 100%;
+}
+
+body {
+  background: #efefef;
+  color: hsl(240,30,10);
+  letter-spacing: 0.125em;
+  text-align: center;
+  /* text-transform: uppercase; */
+
+  -webkit-touch-callout: none; /* iOS Safari */
+    -webkit-user-select: none; /* Safari */
+     -khtml-user-select: none; /* Konqueror HTML */
+       -moz-user-select: none; /* Firefox */
+        -ms-user-select: none; /* Internet Explorer/Edge */
+            user-select: none; /* Non-prefixed version, currently
+                                  supported by Chrome and Opera */
+
+	overflow: hidden;
+}
+
+h1 {
+  margin: 3em 0 2em;
+}
+
+p:focus {
+  border:0;
+}
+
+/***********/
+
+/* 
+   A horrible hack but there's no way to turn
+   off text highlighting in a text area.
+   Instead, make the highlight color the same as the
+   background and font color.
+   I still see artifacts but they're much subtler then
+   the default text highlighting.
+*/
+/*
+::selection {
+  background-color: rgb(255,255,255,1);
+  color: #444444;
+}
+::-moz-selection {
+  background-color: rgb(255,255,255,1);
+  color: #444444;
+}
+::-o-selection {
+  background-color: rgb(255,255,255,1);
+  color: #444444;
+}
+::-ms-selection {
+  background-color: rgb(255,255,255,1);
+  color: #444444;
+}
+::-webkit-selection {
+  background-color: rgb(255,255,255,1);
+  color: #444444;
+}
+*/
+
+.statuslogin {
+  font-size:20px;
+  resize:none;
+  background: #f7f7f7;
+  overflow:hidden;
+  overflow-x:hidden;
+  overflow-y:hidden;
+  word-wrap:off;
+  -webkit-user-select: none;
+  -webkit-touch-callout: none;
+  -khtml-user-select: none;
+  -ms-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+  -moz-user-select: none;
+}
+
+.statusmain {
+  font-size:20px;
+  resize:none;
+  background: #f7f7f7;
+  overflow:auto;
+  overflow-x:hidden;
+  overflow-y:hidden;
+  word-wrap:off;
+  -webkit-user-select: none;
+  -webkit-touch-callout: none;
+  -khtml-user-select: none;
+  -ms-user-select: none;
+  -o-user-select: none;
+  user-select: none;
+  cursor:default;
+  -moz-user-select: none;
+}
+
+.row {
+  height: 80px;
+}
+
+.col {
+  width: 80px;
+}
+
+.bdisp {
+
+  font-size: 20px;
+  font-weight: bold;
+  color: #444444;
+
+  margin-top: 15px;
+  margin-right: 15px;
+  margin-left: auto;
+
+  background: none;
+  border: none;
+}
+
+.bdisp:focus {
+  outline:0;
+}
+
+
+.bmsg {
+
+  font-size: 20px;
+  font-weight: bold;
+  color: #444444;
+
+  background: #ADD8E6;
+  border: solid 2px #888888;
+  box-shadow: 3px 3px 0px #aaaaaa;
+
+}
+
+.bmsg:focus {
+  outline:0;
+}
+
+.bstatus {
+
+  font-size: 20px;
+  font-weight: bold;
+  color: #444444;
+
+  border: solid 2px #888888;
+  box-shadow: 3px 3px 0px #aaaaaa;
+
+}
+
+.bstatus:focus {
+  outline:0;
+}
+
+
+.bdrop {
+
+  /* font-size: 15px; */
+  font-size: 19px;
+  font-weight: bold;
+  color: #444444;
+
+  background: none;
+  border: solid 2px #888888;
+  box-shadow: 3px 3px 0px #aaaaaa;
+
+}
+
+.bdrop:focus {
+  outline:0;
+}
+
+
+.bdropinp {
+
+  font-size: 22px;
+  font-weight: bold;
+  color: #444444;
+
+  background: none;
+  border: solid 2px #888888;
+  box-shadow: 3px 3px 0px #aaaaaa;
+
+  -webkit-transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+  -moz-transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+  transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+}
+
+.bdropinp.ltyellow {
+  background: #ffffe0;
+}
+
+.bdropinp.mny {
+  color: #446444;
+}
+
+.bdropinp.logout {
+  color: #aa4444;
+}
+
+.bdropinp.highlight {
+  background: #aaaaff;
+}
+
+
+.bdropinp:focus {
+  outline:0;
+}
+
+.bdropinp:active {
+  margin-left:9px;
+  background: #aaaaaa;
+
+  -webkit-transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+  -moz-transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+  transition: margin-left 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+
+  -webkit-box-shadow: 0px 0px 0px #8e44ad;
+  -moz-box-shadow: 0px 0px 0px #8e44ad;
+  box-shadow: 0px 0px 0px #8e44ad;
+}
+
+/***********/
+
+.bkey {
+  width: 75px;
+  height:75px;
+}
+
+.bkey:focus {
+  outline:0;
+}
+
+/*
+.bkey {
+  width: 58px;
+  height:58px;
+}
+*/
+
+.bkeym {
+  width: 100px;
+  height:58px;
+}
+
+.bkeym:focus {
+  outline:0;
+}
+
+/*****/
+
+.bkeyw {
+  width: 150px;
+  height:58px;
+}
+
+.bkeyw:focus {
+  outline:0;
+}
+
+/*****/
+
+.bkeyHuge {
+  width: 300px;
+  height:300px;
+}
+
+.bkeyHuge:focus {
+  outline:0;
+}
+
+/*****/
+
+.bfieldinp {
+  width: 150px;
+  height: 58px;
+}
+
+.bfieldinp:focus {
+  outline:0;
+}
+
+/*****/
+
+.btnprv {
+  position: absolute;
+  left: 83%;
+  top: 5%;
+}
+
+.btnnxt {
+  position: absolute;
+  left: 83%;
+  top: 35%;
+}
+
+#mainstatus {
+
+  font-family: "Courier New";
+  font-weight:bold;
+  color: #d7d644;
+  font-size: 16px;
+
+  position:absolute;
+  bottom:0;
+  width:110%;
+  height:25px;
+  background:#555555;
+  /* margin:0; */
+  margin-left:-35px;
+  /* margin-top:5px; */
+  /* padding:0; */
+}
+
+/*****/
+
+.rowmain0 {
+  position: absolute;
+  top: 50%;
+}
+
+.rowmain1 {
+  position: absolute;
+  top: 70%;
+}
+
+/** **/
+
+.invisiblock {
+  /* background: rgba(255,0,0,0.5); */
+  background-color: rgba(0,0,0,0);
+  /* background-color: rgba(255,0,0,0.5); */
+  width: 100px;
+  height: 100px;
+  border: none !important;
+  font-size: 0;
+
+  position: fixed;
+  z-index: 2;
+  outline:0;
+}

+ 294 - 0
busunit/DIUv2/html/css/grids.css

@@ -0,0 +1,294 @@
+/*!
+Pure v1.0.1
+Copyright 2013 Yahoo!
+Licensed under the BSD License.
+https://github.com/pure-css/pure/blob/master/LICENSE.md
+*/
+/*csslint regex-selectors:false, known-properties:false, duplicate-properties:false*/
+
+.pure-g {
+    letter-spacing: -0.31em; /* Webkit: collapse white-space between units */
+    *letter-spacing: normal; /* reset IE < 8 */
+    *word-spacing: -0.43em; /* IE < 8: collapse white-space between units */
+    text-rendering: optimizespeed; /* Webkit: fixes text-rendering: optimizeLegibility */
+
+    /*
+    Sets the font stack to fonts known to work properly with the above letter
+    and word spacings. See: https://github.com/pure-css/pure/issues/41/
+
+    The following font stack makes Pure Grids work on all known environments.
+
+    * FreeSans: Ships with many Linux distros, including Ubuntu
+
+    * Arimo: Ships with Chrome OS. Arimo has to be defined before Helvetica and
+      Arial to get picked up by the browser, even though neither is available
+      in Chrome OS.
+
+    * Droid Sans: Ships with all versions of Android.
+
+    * Helvetica, Arial, sans-serif: Common font stack on OS X and Windows.
+    */
+    font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
+
+    /* Use flexbox when possible to avoid `letter-spacing` side-effects. */
+    display: -webkit-box;
+    display: -webkit-flex;
+    display: -ms-flexbox;
+    display: flex;
+    -webkit-box-orient: horizontal;
+    -webkit-box-direction: normal;
+    -webkit-flex-flow: row wrap;
+        -ms-flex-flow: row wrap;
+            flex-flow: row wrap;
+
+    /* Prevents distributing space between rows */
+    -webkit-align-content: flex-start;
+        -ms-flex-line-pack: start;
+            align-content: flex-start;
+}
+
+/* IE10 display: -ms-flexbox (and display: flex in IE 11) does not work inside a table; fall back to block and rely on font hack */
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+	table .pure-g {
+		display: block;
+	}
+}
+
+/* Opera as of 12 on Windows needs word-spacing.
+   The ".opera-only" selector is used to prevent actual prefocus styling
+   and is not required in markup.
+*/
+.opera-only :-o-prefocus,
+.pure-g {
+    word-spacing: -0.43em;
+}
+
+.pure-u {
+    display: inline-block;
+    *display: inline; /* IE < 8: fake inline-block */
+    zoom: 1;
+    letter-spacing: normal;
+    word-spacing: normal;
+    /* vertical-align: top; */
+    text-rendering: auto;
+}
+
+/*
+Resets the font family back to the OS/browser's default sans-serif font,
+this the same font stack that Normalize.css sets for the `body`.
+*/
+.pure-g [class *= "pure-u"] {
+    font-family: sans-serif;
+}
+
+.pure-u-1,
+.pure-u-1-1,
+.pure-u-1-2,
+.pure-u-1-3,
+.pure-u-2-3,
+.pure-u-1-4,
+.pure-u-3-4,
+.pure-u-1-5,
+.pure-u-2-5,
+.pure-u-3-5,
+.pure-u-4-5,
+.pure-u-5-5,
+.pure-u-1-6,
+.pure-u-5-6,
+.pure-u-1-8,
+.pure-u-3-8,
+.pure-u-5-8,
+.pure-u-7-8,
+.pure-u-1-12,
+.pure-u-5-12,
+.pure-u-7-12,
+.pure-u-11-12,
+.pure-u-1-24,
+.pure-u-2-24,
+.pure-u-3-24,
+.pure-u-4-24,
+.pure-u-5-24,
+.pure-u-6-24,
+.pure-u-7-24,
+.pure-u-8-24,
+.pure-u-9-24,
+.pure-u-10-24,
+.pure-u-11-24,
+.pure-u-12-24,
+.pure-u-13-24,
+.pure-u-14-24,
+.pure-u-15-24,
+.pure-u-16-24,
+.pure-u-17-24,
+.pure-u-18-24,
+.pure-u-19-24,
+.pure-u-20-24,
+.pure-u-21-24,
+.pure-u-22-24,
+.pure-u-23-24,
+.pure-u-24-24 {
+    display: inline-block;
+    *display: inline;
+    zoom: 1;
+    letter-spacing: normal;
+    word-spacing: normal;
+    vertical-align: top;
+    text-rendering: auto;
+}
+
+.pure-u-1-24 {
+    width: 4.1667%;
+    *width: 4.1357%;
+}
+
+.pure-u-1-12,
+.pure-u-2-24 {
+    width: 8.3333%;
+    *width: 8.3023%;
+}
+
+.pure-u-1-8,
+.pure-u-3-24 {
+    width: 12.5000%;
+    *width: 12.4690%;
+}
+
+.pure-u-1-6,
+.pure-u-4-24 {
+    width: 16.6667%;
+    *width: 16.6357%;
+}
+
+.pure-u-1-5 {
+    width: 20%;
+    *width: 19.9690%;
+}
+
+.pure-u-5-24 {
+    width: 20.8333%;
+    *width: 20.8023%;
+}
+
+.pure-u-1-4,
+.pure-u-6-24 {
+    width: 25%;
+    *width: 24.9690%;
+}
+
+.pure-u-7-24 {
+    width: 29.1667%;
+    *width: 29.1357%;
+}
+
+.pure-u-1-3,
+.pure-u-8-24 {
+    width: 33.3333%;
+    *width: 33.3023%;
+}
+
+.pure-u-3-8,
+.pure-u-9-24 {
+    width: 37.5000%;
+    *width: 37.4690%;
+}
+
+.pure-u-2-5 {
+    width: 40%;
+    *width: 39.9690%;
+}
+
+.pure-u-5-12,
+.pure-u-10-24 {
+    width: 41.6667%;
+    *width: 41.6357%;
+}
+
+.pure-u-11-24 {
+    width: 45.8333%;
+    *width: 45.8023%;
+}
+
+.pure-u-1-2,
+.pure-u-12-24 {
+    width: 50%;
+    *width: 49.9690%;
+}
+
+.pure-u-13-24 {
+    width: 54.1667%;
+    *width: 54.1357%;
+}
+
+.pure-u-7-12,
+.pure-u-14-24 {
+    width: 58.3333%;
+    *width: 58.3023%;
+}
+
+.pure-u-3-5 {
+    width: 60%;
+    *width: 59.9690%;
+}
+
+.pure-u-5-8,
+.pure-u-15-24 {
+    width: 62.5000%;
+    *width: 62.4690%;
+}
+
+.pure-u-2-3,
+.pure-u-16-24 {
+    width: 66.6667%;
+    *width: 66.6357%;
+}
+
+.pure-u-17-24 {
+    width: 70.8333%;
+    *width: 70.8023%;
+}
+
+.pure-u-3-4,
+.pure-u-18-24 {
+    width: 75%;
+    *width: 74.9690%;
+}
+
+.pure-u-19-24 {
+    width: 79.1667%;
+    *width: 79.1357%;
+}
+
+.pure-u-4-5 {
+    width: 80%;
+    *width: 79.9690%;
+}
+
+.pure-u-5-6,
+.pure-u-20-24 {
+    width: 83.3333%;
+    *width: 83.3023%;
+}
+
+.pure-u-7-8,
+.pure-u-21-24 {
+    width: 87.5000%;
+    *width: 87.4690%;
+}
+
+.pure-u-11-12,
+.pure-u-22-24 {
+    width: 91.6667%;
+    *width: 91.6357%;
+}
+
+.pure-u-23-24 {
+    width: 95.8333%;
+    *width: 95.8023%;
+}
+
+.pure-u-1,
+.pure-u-1-1,
+.pure-u-5-5,
+.pure-u-24-24 {
+    width: 100%;
+}

+ 566 - 0
busunit/DIUv2/html/index-ORG.html

@@ -0,0 +1,566 @@
+<html>
+
+  <head>
+
+    <link rel="stylesheet" href="css/diustyles.css">
+    <link rel="stylesheet" href="css/grids.css">
+
+
+  </head>
+
+  <body>
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******    Login   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_login' >
+
+      <br>
+
+      <div class='pure-g col'>
+
+        <div class='pure-u-1-3 row'> </div>
+        <div class='pure-u-1-2 row'> <button class='bdropinp bkeyw' id='ui_login_login'>Login</button> </div>
+
+      </div>
+
+      <br>
+      <br>
+      <br>
+
+      <div class='pure-g'>
+
+        <button class='invisiblock' id='ui_login_blockwindow'> </button>
+
+<textarea class='statuslogin' type='textarea' id='ui_login_status' rows='12' cols='80' disabled readonly>
+Tunnel: YES   GPRS: YES   Eq# 9998  #Msg: 0
+Last Token Read (00): ""
+GPS: NO / Stale
+
+Package    Version        Installed
+config     20190730v403   11/05/2019 02:36:43
+firmware   1.11           07/30/2019 16:33:08
+
+IMEI = 356136074279052
+IMSI = 310260877138191
+ETH0 = 00:80:66:10:E8:8A
+</textarea>
+
+      </div>
+
+    </div>
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Driver   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+    <div id='ui_driver' style='display:none;'>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_1'>1</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_2'>2</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_3'>3</button> </div>
+
+        <div class='pure-u-1-6 col'> <p><button class='bdisp' style='display:block;' id='ui_driver_drivertext'>Driver</button></p> </div>
+
+        <div class='pure-u-1-6 col'> 
+          <button class="bdrop bfieldinp" id='ui_driver_driver' style='display:block;'></button>
+        </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_4'>4</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_5'>5</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_6'>6</button> </div>
+
+        <div class='pure-u-1-6 col' style='text-align:center;'>
+          <p><button class='bdisp' style='display:none;' id='ui_driver_pin_text'>Pin</button></p>
+        </div>
+
+        <div class='pure-u-1-6 col'> 
+          <button class="bdrop bfieldinp" id='ui_driver_pin' style='display:none;'></button>
+        </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_7'>7</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_8'>8</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_9'>9</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_driver_ok'>Ok</button> </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_clr'>Clr</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_0'>0</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_driver_bksp'>Bksp</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_driver_cancel'>Cancel</button> </div>
+
+      </div>
+
+    </div> <!-- ui_driver -->
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Driver   ******* -->
+    <!-- ******   Verify   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+    <div id='ui_driververify' style='display:none;'>
+
+      <br>
+      <div class='pure-g'> </div>
+      <br> <br> <br>
+      <div class='pure-g'> </div>
+      <br> <br> <br>
+
+      <div class='pure-g'>
+        <div class='pure-u-1-6'> <button class='bstatus'>Verifying Driver</button> </div>
+      </div>
+
+      <br> <br> <br> 
+    </div>
+
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Driver   ******* -->
+    <!-- ******  Incorrect ******* -->
+    <!-- ******   Login    ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+    <div id='ui_driverincorrect' style='display:none;'>
+
+      <div style='width:100%; height:100%;'>
+
+        <div class='pure-g row' style='width:100%; height:100%;' >
+          <div class='pure-u-1-6 col' style=' position:absolute; top:20%; margin-left:25%; '> <button class='bdropinp bkeyHuge' id='ui_driverincorrect_btn'>Incorrect Login</button> </div>
+        </div>
+
+      </div>
+
+    </div>
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Paddle   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_paddle' style='display:none;'>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_1'>1</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_2'>2</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_3'>3</button> </div>
+
+        <div class='pure-u-1-6 col'>
+          <p><button class='bdisp' id='ui_paddle_paddle_text' style='display:block;'>Paddle</button></p>
+        </div>
+
+        <div class='pure-u-1-6 col'> 
+          <button class="bdrop bfieldinp" id='ui_paddle_paddle' style='display:block;'></button>
+        </div>
+
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_4'>4</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_5'>5</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_6'>6</button> </div>
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_7'>7</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_8'>8</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_9'>9</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_paddle_ok'>Ok</button> </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_clr'>Clr</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_0'>0</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_paddle_bksp'>Bksp</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_paddle_cancel'>Cancel</button> </div>
+
+      </div>
+
+    </div> <!-- ui_paddle -->
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Paddle   ******* -->
+    <!-- ******   Verify   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+    <div id='ui_paddleverify' style='display:none;'>
+
+      <br>
+      <div class='pure-g'> </div>
+      <br> <br> <br>
+      <div class='pure-g'> </div>
+      <br> <br> <br>
+
+      <div class='pure-g'>
+        <div class='pure-u-1-6'> <button class='bstatus'>Verifying Paddle</button> </div>
+      </div>
+
+      <br> <br> <br> 
+    </div>
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Unknown  ******* -->
+    <!-- ******   Paddle   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+    <div id='ui_paddleunknown' style='display:none;'>
+
+      <!--
+      <br>
+      <div class='pure-g row'>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_paddleunknown_btn'>Unknown Paddle</button> </div>
+      </div>
+      -->
+
+      <div style='width:100%; height:100%;'>
+
+        <div class='pure-g row' style='width:100%; height:100%;' >
+          <div class='pure-u-1-6 col' style=' position:absolute; top:20%; margin-left:25%; '>
+            <button class='bdropinp bkeyHuge' id='ui_paddleunknown_btn'>Unknown Paddle </button>
+          </div>
+        </div>
+
+      </div>
+
+
+
+    </div>
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   main     ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_main' style='display:none;'>
+
+      <div class='pure-g row'>
+
+        <button class='invisiblock' id='ui_main_blockwindow'> </button>
+
+<textarea wrap="" class='statusmain' type='textarea' id='ui_main_status' rows='10' cols='40' onselect='return false;' unselectable='on' disabled readonly>
+012345678901234567890123456789012345678901234567890
+one
+two
+three
+four
+five
+six
+seeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeven
+eight
+nine
+ten
+eleven
+twelve
+thirtheen
+
+</textarea>
+
+        <!-- <div class='pure-u-1-2 col'> <button class='bstatus' id='ui_main_status'>status...</button> </div> -->
+
+      </div>
+
+      <div class='pure-u-1-6 col'> <button class='bdropinp bkey btnprv' id='ui_main_prv'>PRV</button> </div>
+      <div class='pure-u-1-6 col'> <button class='bdropinp bkey btnnxt' id='ui_main_nxt'>NXT</button> </div>
+
+      <div class='pure-g row'></div>
+      <!-- <div class='pure-g row'></div> -->
+      <div style='height:85;'></div>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_adult'>Adult $</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_youth'>Youth $</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_half'>Half $</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_main_bulk'>Bulk $</button> </div>
+
+      </div>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_bike'>Bike</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_wheelchair'>Wheel Chair</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym mny' id='ui_main_transfer'>X-fer</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_main_menu'>Menu</button> </div>
+
+      </div>
+
+      <div id="mainstatus">Rt 9900   Trip 1   Stop 0   GPS No   Tun Yes   2019-08-13 04:58</div>
+
+    </div> <!-- ui_main -->
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Bulk     ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_bulk' style='display:none;'>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym highlight' id='ui_bulk_misc'>$ + Misc</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_bulk_passes'>Passes</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_bulk_menu'>Main Menu</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdisp' style='font-size:30px;'>BULK</button> </div>
+
+      </div>
+
+      <hr>
+
+      <br> <br> <br> 
+
+      <div id='ui_bulk_misc_tab' style='display:block;'>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_adult'>Adult $</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_youth'>Youth $</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_half'>Half $</button> </div>
+        </div>
+
+        <div class='pure-g row'></div>
+
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_event'>Event</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_transfer'>X-fer</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_interline'>InterLine</button> </div>
+        </div>
+
+      </div>
+
+      <div id='ui_bulk_passes_tab' style='display:none;'>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_schoola'>SchoolA ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_schoolb'>SchoolB ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_schoolc'>SchoolC ID</button> </div>
+        </div>
+
+        <div class='pure-g row'></div>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_orga'>Org A ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_orgb'>Org B ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_bulk_orgc'>Org C ID</button> </div>
+        </div>
+
+      </div>
+
+
+
+    </div> <!-- ui_bulk -->
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******    Bulk    ******* -->
+    <!-- ******   Accept   ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_bulkaccept' style='display:none;'>
+
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_1'>1</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_2'>2</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_3'>3</button> </div>
+
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> 
+          <button class="bdropinp bkeyw" id='ui_bulkaccept_faretype' style='display:block;'>...</button>
+
+
+        </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_4'>4</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_5'>5</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_6'>6</button> </div>
+
+
+        <div class='pure-u-1-6 col'> <p><button class='bdisp' style='display:block;' id='ui_driver_drivertext'>#</button></p> </div>
+        <div class='pure-u-1-6 col'> 
+          <button class="bdropinp bkeyw" id='ui_bulkaccept_count' style='display:block;'></button>
+        </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_7'>7</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_8'>8</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_9'>9</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_bulkaccept_ok'>Ok</button> </div>
+
+      </div>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_clr'>Clr</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_0'>0</button> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkey ltyellow' id='ui_bulkaccept_bksp'>Bksp</button> </div>
+
+        <div class='pure-u-1-6 col'> </div>
+        <div class='pure-u-1-6 col'> <button class='bdropinp bkeyw' id='ui_bulkaccept_cancel'>Cancel</button> </div>
+
+      </div>
+
+
+    </div> <!-- ui_bulk -->
+
+
+    <!-- ************************* -->
+    <!-- ******            ******* -->
+    <!-- ******   Fare     ******* -->
+    <!-- ******   Menu     ******* -->
+    <!-- ******            ******* -->
+    <!-- ************************* -->
+
+
+    <div id='ui_fareoverride' style='display:none;'>
+
+      <br>
+
+      <div class='pure-g row'>
+
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym highlight' id='ui_fareoverride_misc'>$ + Misc</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_fareoverride_passes'>Passes</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym' id='ui_fareoverride_menu'>Main Menu</button> </div>
+        <div class='pure-u-1-4 col'> <button class='bdropinp bkeym logout' id='ui_fareoverride_logout' style='float:center;'>Logout</button> </div>
+
+      </div>
+
+      <hr>
+
+      <br> <br> <br> 
+
+      <div id='ui_fareoverride_misc_tab' style='display:block;'>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_adult'>Adult $</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_youth'>Youth $</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_half'>Half $</button> </div>
+        </div>
+
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_bike'>Bike</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_wheelchair'>Wheel Chair</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_transfer'>X-fer</button> </div>
+        </div>
+
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_event'>Event</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_interline'>Interline</button> </div>
+        </div>
+
+      </div>
+
+      <div id='ui_fareoverride_passes_tab' style='display:none;'>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_schoola'>SchoolA ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_schoolb'>SchoolB ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_schoolc'>SchoolC ID</button> </div>
+        </div>
+
+        <div class='pure-g row'></div>
+
+        <div class='pure-g row'>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_orga'>OrgA ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_orgb'>OrgB ID</button> </div>
+          <div class='pure-u-1-3 col'> <button class='bdropinp bkeyw mny' id='ui_fareoverride_orgc'>OrgC</button> </div>
+        </div>
+
+      </div>
+
+
+
+    </div> <!-- ui_fareoverride -->
+
+
+  </body>
+
+  <script src='js/diu_ui.js'></script>
+
+</html>

+ 1 - 0
busunit/DIUv2/html/index.html

@@ -0,0 +1 @@
+index-ORG.html

+ 668 - 0
busunit/DIUv2/html/js/diu_ui-ORG.js

@@ -0,0 +1,668 @@
+
+var _URL = "http://localhost";
+var _PORT = 60535;
+
+var g_ctx = {
+
+  "driver_login_state" : "driver",
+
+  "driver" : "",
+  "pin" : "",
+  "paddle" : "",
+
+  "current_ui" : "ui_login",
+
+  "ui_change_timeoutid": -1,
+
+  "bulkfare" : "",
+  "bulkfare_count" : "",
+
+  "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();
+  //var url = _URL + ":" + _PORT + "/req";
+  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<param_name.length; ii++) {
+    varstr += "&" + param_name[ii] + "=" + param_val[ii];
+  }
+
+  req.onreadystatechange = function() {
+    if (req.readyState == 4) {
+      if (req.status == 200) {
+
+        var fulltxt = req.responseText;
+        var resp = req.responseText.split(" ");
+
+        if ((resp.length>=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 {
+  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 _switch_ui(to) {
+  var ele;
+
+  console.log(">>>to", to);
+
+  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") ||
+      (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 _clear_ui_driver() {
+  var ele;
+
+  var u = ["driver", "pin"];
+
+  for (var i=0; i<u.length; i++) {
+    g_ctx[u[i]] = "";
+    ele = document.getElementById("ui_driver_" + u[i]);
+    ele.innerHTML = "";
+    ele.style.background = "";
+  }
+
+  ele = document.getElementById("ui_driver_pin");
+  ele.style.display = "none";
+
+  ele = document.getElementById("ui_driver_pin_text");
+  ele.style.display = "none";
+
+}
+
+function _clear_ui_paddle() {
+  g_ctx.paddle = "";
+  var ele = document.getElementById("ui_paddle_paddle");
+  ele.innerHTML = "";
+}
+
+function _clear_ui_bulkaccept() {
+  var ele;
+
+  g_ctx.bulkfare = "";
+  ele = document.getElementById("ui_bulkaccept_faretype");
+  ele.innerHTML = "";
+
+  g_ctx.bulkfare_count = "";
+  ele = document.getElementById("ui_bulkaccept_count");
+  ele.innerHTML = "";
+}
+
+function _login() {
+  _switch_ui('ui_driver');
+  g_ctx.driver_login_state = "driver";
+  _clear_ui_driver();
+  _clear_ui_paddle();
+}
+
+//------------
+//------------
+
+
+function _verify_driver() {
+  var driver = g_ctx.driver;
+  var pin = g_ctx.pin;
+
+  _api_request("driverlogin", {"driver":driver, "pin":pin}, _verify_driver_ok, _verify_driver_fail);
+  return;
+}
+
+function _verify_driver_ok()      { _switch_ui("ui_paddle"); }
+function _verify_driver_fail()    { _switch_ui("ui_driverincorrect");  }
+function _driver_incorrect(inp)  {
+  _clear_ui_driver();
+  _switch_ui("ui_driver");
+}
+
+//------------
+
+function _driver_login(inp) {
+
+  var uvar = "";
+  if (g_ctx.driver_login_state == "driver")       { uvar = "driver"; }
+  else if (g_ctx.driver_login_state == "pin")     { uvar = "pin"; }
+  else {
+    console.log("_driver_login: ERROR: unknown driver state \"" + g_ctx.driver_login_state + "\"");
+    return;
+  }
+
+  var n = g_ctx[uvar].length;
+
+  //if (inp == 'cancel') { _switch_ui('ui_driver', 'ui_login'); }
+  if (inp == 'cancel') { _switch_ui('ui_login'); }
+  else if (inp == 'ok')     {
+
+    if (uvar == "driver") {
+      g_ctx.driver_login_state = "pin";
+
+      var ele;
+      ele = document.getElementById("ui_driver_driver");
+      ele.style.background = "#aaaaaa";
+
+      ele = document.getElementById("ui_driver_pin");
+      ele.style.display = "block";
+      ele = document.getElementById("ui_driver_pin_text");
+      ele.style.display = "block";
+
+    }
+    else if (uvar == "pin") {
+      g_ctx.driver_login_state = "driver";
+
+
+      //_verify_driver();
+      //_switch_ui("ui_driver", "ui_driververify");
+
+      _verify_driver();
+      g_ctx.ui_change_timeoutid = window.setTimeout(function() {
+        _switch_ui("ui_driververify");
+      }, 150);
+
+      return;
+    }
+
+  }
+
+  // manage adding/subtracting/clearing relevant field
+  //
+  else if (inp == 'bksp')   { g_ctx[uvar] = g_ctx[uvar].substr(0, n-1); }
+  else if (inp == 'clr')    { g_ctx[uvar]= ""; }
+  else                      { g_ctx[uvar] += inp; }
+
+  // Pin should not be displayed on screen.
+  // Use '*' to hide it.
+  //
+  if (uvar == "pin") {
+    var n = g_ctx[uvar].length;
+    var x = "";
+    for (i=0; i<n; i++) { x += "*"; }
+    var ele = document.getElementById('ui_driver_' + uvar);
+    ele.innerHTML = x;
+  }
+
+  // Otherwise update the displayed (driver number)
+  //
+  else {
+    var ele = document.getElementById('ui_driver_' + uvar);
+    ele.innerHTML = g_ctx[uvar];
+  }
+
+}
+
+//------------
+//------------
+
+
+function _verify_paddle() {
+  var paddle = g_ctx.paddle;
+
+  _api_request("paddleinput", {"paddle":paddle}, _verify_paddle_ok, _verify_paddle_fail);
+  return;
+}
+
+function _verify_paddle_ok()    { _switch_ui("ui_main"); }
+function _verify_paddle_fail()  { _switch_ui("ui_paddleunknown"); }
+function _paddle_unknown(inp)   {
+  _clear_ui_paddle();
+  _switch_ui("ui_paddle");
+}
+
+//------------
+
+function _paddle_input(inp) {
+  var n = g_ctx.paddle.length;
+
+  if (inp == 'cancel')    { _switch_ui('ui_login'); }
+  else if (inp == 'ok')   {
+    _verify_paddle();
+
+    g_ctx.ui_change_timeoutid = window.setTimeout(function() {
+      _switch_ui("ui_paddleverify");
+    }, 150);
+
+    return;
+  }
+  else if (inp == 'bksp') { g_ctx.paddle = g_ctx.paddle.substr(0, n-1); }
+  else if (inp == 'clr')  { g_ctx.paddle = ""; }
+  else                    { g_ctx.paddle  += inp; }
+
+  // Otherwise update the displayed (driver number)
+  //
+  var ele = document.getElementById('ui_paddle_paddle');
+  ele.innerHTML = g_ctx.paddle;
+}
+
+//-------------
+//-------------
+//-------------
+
+function _main_prv() {
+  console.log("prv");
+  _api_request("prevstop");
+}
+
+function _main_nxt() {
+  console.log("nxt");
+  _api_request("nextstop");
+}
+
+function _fare_adult() {
+  console.log("fare adult");
+  _api_request("fare", {"fare":"adult","count":1});
+}
+
+function _fare_youth() {
+  console.log("fare youth");
+  _api_request("fare", {"fare":"youth","count":1});
+}
+
+function _fare_half() {
+  console.log("fare half");
+  _api_request("fare", {"fare":"half","count":1});
+}
+
+function _fare_bike() {
+  console.log("fare bike");
+  _api_request("fare", {"fare":"bike","count":1});
+}
+
+function _fare_wheelchair() {
+  console.log("fare wheelchair");
+  _api_request("fare", {"fare":"wheelchair","count":1});
+}
+
+function _fare_transfer() {
+  console.log("fare transfer");
+  _api_request("fare", {"fare":"transfer","count":1});
+}
+
+//-------------
+//-------------
+//-------------
+
+function _main_bulk() {
+  _show_ui_element("ui_bulk_misc_tab");
+  _hide_ui_element("ui_bulk_passes_tab");
+  _switch_ui("ui_bulk");
+}
+
+function _main_menu() {
+  _switch_ui("ui_fareoverride");
+}
+
+//-------------
+//-------------
+//-------------
+
+
+function _bulkaccept_ok() {
+  console.log("bulkfare:", g_ctx.bulkfare, ", count:", g_ctx.bulkfare_count);
+  _switch_ui("ui_main");
+
+  _api_request("fare",{"fare":g_ctx.bulkfare,"count":g_ctx.bulkfare_count});
+}
+
+function _bulkaccept_cancel() {
+  _switch_ui("ui_main");
+}
+
+function _bulkaccept_input(inp) {
+  var n = g_ctx.bulkfare_count.length;
+
+  if (inp == 'cancel')    { _switch_ui('ui_main'); }
+  else if (inp == 'ok')   { _bulkaccept_ok(); return; }
+  else if (inp == 'bksp') { g_ctx.bulkfare_count = g_ctx.bulkfare_count.substr(0, n-1); }
+  else if (inp == 'clr')  { g_ctx.bulkfare_count = ""; }
+  else                    { g_ctx.bulkfare_count += inp; }
+
+  // Otherwise update the displayed (driver number)
+  //
+  var ele = document.getElementById('ui_bulkaccept_count');
+  ele.innerHTML = g_ctx.bulkfare_count;
+}
+
+
+//-------------
+//-------------
+//-------------
+
+function _cb_status(inp) {
+  //console.log("_cb_status>>\n", inp);
+
+  var fields = inp.substr(3).split(";");
+  var fv = {};
+
+  for (var ii=0; ii<fields.length; ii++) {
+    var kv = fields[ii].split("=");
+    fv[kv[0]] = kv[1];
+  }
+
+  //for (var x in fv) { console.log(x, ";;;", fv[x]); }
+
+
+}
+
+function _cb_status_err(e) {
+  console.log("ERROR: _cb_status_err:", e);
+}
+
+//-------------
+//-------------
+//-------------
+
+function init() {
+
+  // login
+  //
+  document.getElementById('ui_login_login').onclick = _login;
+  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;
+
+  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<simple_fares.length; ii++) {
+    var fare = simple_fares[ii];
+    document.getElementById('ui_main_' + fare).onclick = simple_fares_f[ii];
+  }
+
+  // bulk menu buttons
+  //
+  document.getElementById('ui_bulk_passes').onclick =
+    function() {
+      var ele;
+      ele = document.getElementById("ui_bulk_misc");
+      ele.classList.remove("highlight");
+      ele = document.getElementById("ui_bulk_passes");
+      ele.classList.add("highlight");
+
+      _hide_ui_element("ui_bulk_misc_tab");
+      _show_ui_element("ui_bulk_passes_tab");
+    };
+
+  document.getElementById('ui_bulk_misc').onclick =
+    function() {
+      var ele;
+      ele = document.getElementById("ui_bulk_misc");
+      ele.classList.add("highlight");
+      ele = document.getElementById("ui_bulk_passes");
+      ele.classList.remove("highlight");
+
+
+      _show_ui_element("ui_bulk_misc_tab");
+      _hide_ui_element("ui_bulk_passes_tab");
+    };
+
+  document.getElementById('ui_bulk_menu').onclick = function() { _switch_ui("ui_main"); }
+
+  var bulk_pass = ["adult", "youth", "half", "event", "transfer", "interline",
+                    "schoola", "schoolb", "schoolc", "orga", "orgb", "orgc"];
+  var bulk_pass_name = ["Adult Cash", "Youth Cash", "Half Cash", "Special Event", "Transfer", "Interline",
+                        "School A", "Sschool B", "School C", "Org A", "Org B", "Org C"];
+  for (var i=0; i<bulk_pass.length; i++) {
+    var p = bulk_pass[i];
+    var u = bulk_pass_name[i];
+    var ele = document.getElementById('ui_bulk_' + p);
+    ele.onclick = (function(x,y) {
+      return function() {
+        _clear_ui_bulkaccept();
+        g_ctx.bulkfare = x;
+        _switch_ui("ui_bulkaccept");
+        var ee = document.getElementById("ui_bulkaccept_faretype");
+        ee.innerHTML = y;
+      };
+    })(p, u);
+  }
+
+
+  // bulk accept fares
+  //
+  document.getElementById('ui_bulkaccept_ok').onclick = _bulkaccept_ok;
+  document.getElementById('ui_bulkaccept_cancel').onclick = _bulkaccept_cancel;
+
+
+  // fareoverride menu buttons
+  //
+  document.getElementById('ui_fareoverride_passes').onclick =
+    function() {
+      var ele;
+      ele = document.getElementById("ui_fareoverride_misc");
+      ele.classList.remove("highlight");
+      ele = document.getElementById("ui_fareoverride_passes");
+      ele.classList.add("highlight");
+
+      _hide_ui_element("ui_fareoverride_misc_tab");
+      _show_ui_element("ui_fareoverride_passes_tab");
+    };
+
+  document.getElementById('ui_fareoverride_misc').onclick =
+    function() {
+      var ele;
+      ele = document.getElementById("ui_fareoverride_misc");
+      ele.classList.add("highlight");
+      ele = document.getElementById("ui_fareoverride_passes");
+      ele.classList.remove("highlight");
+
+      _show_ui_element("ui_fareoverride_misc_tab");
+      _hide_ui_element("ui_fareoverride_passes_tab");
+    };
+
+  document.getElementById('ui_fareoverride_menu').onclick = function() { _switch_ui("ui_main"); }
+  document.getElementById('ui_fareoverride_logout').onclick =
+    function() {
+      _api_request("logout");
+      _switch_ui("ui_login");
+    }
+
+  var override_pass = [ "adult", "youth", "half",
+                        "bike", "wheelchair", "transfer",
+                        "event", "interline",
+                        "schoola", "schoolb", "schoolc",
+                        "orga", "orgb", "orgc" ];
+  for (var i=0; i<override_pass.length; i++) {
+    var p = override_pass[i];
+    var ele = document.getElementById("ui_fareoverride_" + p);
+    ele.onclick = (function(x) {
+      return function() { _api_request("fare", {"fare":x,"count":1}); };
+    })(p);
+  }
+
+
+  var ui_page = [ "driver", "paddle", "bulkaccept" ];
+  var ui_func = [ _driver_login, _paddle_input, _bulkaccept_input ];
+
+  for (var idx=0; idx<ui_page.length; idx++) {
+
+    var c = ui_page[idx];
+    var f = ui_func[idx];
+
+    for (var i=0; i<=9; i++) {
+      document.getElementById('ui_' + c + '_' + i).onclick =
+        (function(_f, x) { return function() { _f(x); } })(f, i);
+    }
+    document.getElementById('ui_' + c + '_' + 'bksp').onclick =
+      (function(_f,x) { return function() { _f(x); } })(f, 'bksp');
+    document.getElementById('ui_' + c + '_' + 'clr').onclick =
+      (function(_f,x) { return function() { _f(x); } })(f, 'clr');
+    document.getElementById('ui_' + c + '_' + 'ok').onclick =
+      (function(_f,x) { return function() { _f(x); } })(f, 'ok');
+    document.getElementById('ui_' + c + '_' + 'cancel').onclick =
+      (function(_f,x) { return function() { _f(x); } })(f, 'cancel');
+
+  }
+
+  // set interval to check status every 1 second
+  //
+  var x = window.setInterval(function() { _api_request("status", {}, _cb_status, _cb_status_err); }, 1000);
+  console.log(">>>", x);
+
+  // try and reduce textarea highlighting, drag and drop/copy pasting,
+  // and other bad behavor.
+  //
+  var ele;
+  var block_ele;
+  var rect;
+
+  ele = document.getElementById("ui_login_status");
+  ele.ondragstart = function() { return false; }
+  ele.onselectstart = function() { return false; }
+  ele.onmousedown = function() { return false; }
+  ele.ondragstart = function() { return false; }
+
+  rect = ele.getBoundingClientRect();
+  block_ele = document.getElementById("ui_login_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;
+
+
+  ele = document.getElementById("ui_main_status");
+  ele.ondragstart = function() { return false; }
+  ele.onselectstart = function() { return false; }
+  ele.onmousedown = function() { return false; }
+  ele.ondragstart = function() { return false; }
+
+  rect = ele.getBoundingClientRect();
+  block_ele = document.getElementById("ui_main_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;
+
+
+}
+
+init();

+ 1 - 0
busunit/DIUv2/html/js/diu_ui.js

@@ -0,0 +1 @@
+diu_ui-ORG.js

+ 192 - 0
busunit/DIUv2/mkgmtime.c

@@ -0,0 +1,192 @@
+/*this guts of this file come from the following source*/
+/*standing on the shoulders of giants and all*/
+/*I have stripped it down to minimize gross namespace collisions and*/
+/*reduce complexity as I only really need the mkgmtime function*/
+
+
+/* free mktime function
+   Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
+   and Michael Haertel <mike@ai.mit.edu>
+   Unlimited distribution permitted provided this copyright notice is
+   retained and any functional modifications are prominently identified.  */
+
+/* Revised 1997 by Christian Spieler:
+   The code was changed to get more conformance with ANSI's (resp. modern
+   UNIX releases) definition for mktime():
+   - Added adjustment for out-of-range values in the fields of struct tm.
+   - Added iterations to get the correct UTC result for input values at
+     the gaps when daylight saving time is switched on or off.
+   - Allow forcing of DST "on" or DST "off" by setting `tm_isdst' field in
+     the tm struct to positive number resp. zero. The `tm_isdst' field must
+     be negative on entrance of mktime() to enable automatic determination
+     if DST is in effect for the requested local time.
+   - Added optional check for overflowing the time_t range.  */
+
+/* Note: This version of mktime is ignorant of the tzfile.
+   When the tm structure passed to mktime represents a local time that
+   is valid both as DST time and as standard time (= time value in the
+   gap when switching from DST back to standard time), the behaviour
+   for `tm_isdst < 0' depends on the current timezone: TZ east of GMT
+   assumes winter time, TZ west of GMT assumes summer time.
+   Although mktime() (resp. mkgmtime()) tries to adjust for invalid values
+   of struct tm members, this may fail for input values that are far away
+   from the valid ranges. The adjustment process does not check for overflows
+   or wrap arounds in the struct tm components.  */
+
+#include <time.h>
+#include <stdio.h>
+
+#ifndef NO_TIME_T_MAX
+   /* Provide default values for the upper limit of the time_t range.
+      These are the result of the decomposition into a `struct tm' for
+      the time value 0xFFFFFFFEL ( = (time_t)-2 ).
+      Note: `(time_t)-1' is reserved for "invalid time"!  */
+#  ifndef TM_YEAR_MAX
+#    define TM_YEAR_MAX         2106
+#  endif
+#  ifndef TM_MON_MAX
+#    define TM_MON_MAX          1       /* February */
+#  endif
+#  ifndef TM_MDAY_MAX
+#    define TM_MDAY_MAX         7
+#  endif
+#  ifndef TM_HOUR_MAX
+#    define TM_HOUR_MAX         6
+#  endif
+#  ifndef TM_MIN_MAX
+#    define TM_MIN_MAX          28
+#  endif
+#  ifndef TM_SEC_MAX
+#    define TM_SEC_MAX          14
+#  endif
+#endif /* NO_TIME_T_MAX */
+
+/* Adjusts out-of-range values for `tm' field `tm_member'. */
+#define ADJUST_TM(tm_member, tm_carry, modulus) \
+  if ((tm_member) < 0) { \
+    tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
+    tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
+  } else if ((tm_member) >= (modulus)) { \
+    tm_carry += (tm_member) / (modulus); \
+    tm_member = (tm_member) % (modulus); \
+  }
+
+/* Nonzero if `y' is a leap year, else zero. */
+#define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
+
+/* Number of leap years from 1970 to `y' (not including `y' itself). */
+#define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
+
+/* Additional leapday in February of leap years. */
+#define leapday(m, y) ((m) == 1 && leap (y))
+
+/* Length of month `m' (0 .. 11) */
+#define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
+
+/* Accumulated number of days from 01-Jan up to start of current month. */
+static const short ydays[] =
+{
+  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+};
+
+/* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
+   of the Greenwich Mean time and date in the exploded time structure `tm'.
+   This function does always put back normalized values into the `tm' struct,
+   parameter, including the calculated numbers for `tm->tm_yday',
+   `tm->tm_wday', and `tm->tm_isdst'.
+   Returns -1 if the time in the `tm' parameter cannot be represented
+   as valid `time_t' number. */
+
+time_t mkgmtime(struct tm *tm)
+{
+  int years, months, days, hours, minutes, seconds;
+
+  years = tm->tm_year + 1900;   /* year - 1900 -> year */
+  months = tm->tm_mon;          /* 0..11 */
+  days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
+  hours = tm->tm_hour;          /* 0..23 */
+  minutes = tm->tm_min;         /* 0..59 */
+  seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
+
+  ADJUST_TM(seconds, minutes, 60)
+  ADJUST_TM(minutes, hours, 60)
+  ADJUST_TM(hours, days, 24)
+  ADJUST_TM(months, years, 12)
+  if (days < 0)
+    do {
+      if (--months < 0) {
+        --years;
+        months = 11;
+      }
+      days += monthlen(months, years);
+    } while (days < 0);
+  else
+    while (days >= monthlen(months, years)) {
+      days -= monthlen(months, years);
+      if (++months >= 12) {
+        ++years;
+        months = 0;
+      }
+    }
+
+  /* Restore adjusted values in tm structure */
+  tm->tm_year = years - 1900;
+  tm->tm_mon = months;
+  tm->tm_mday = days + 1;
+  tm->tm_hour = hours;
+  tm->tm_min = minutes;
+  tm->tm_sec = seconds;
+
+  /* Set `days' to the number of days into the year. */
+  days += ydays[months] + (months > 1 && leap (years));
+  tm->tm_yday = days;
+
+  /* Now calculate `days' to the number of days since Jan 1, 1970. */
+  days = (unsigned)days + 365 * (unsigned)(years - 1970) +
+         (unsigned)(nleap (years));
+  tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
+  tm->tm_isdst = 0;
+
+  if (years < 1970)
+    return (time_t)-1;
+
+#if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
+#if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
+  if (years > TM_YEAR_MAX ||
+      (years == TM_YEAR_MAX &&
+       (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+                      (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
+        (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
+                        (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
+         (hours > TM_HOUR_MAX ||
+          (hours == TM_HOUR_MAX &&
+           (minutes > TM_MIN_MAX ||
+            (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
+    return (time_t)-1;
+#endif
+#endif
+
+  return (time_t)(86400L * (unsigned long)(unsigned)days +
+                  3600L * (unsigned long)hours +
+                  (unsigned long)(60 * minutes + seconds));
+}
+
+/*
+int main()
+{
+  struct tm crud;
+  time_t now,then;
+  
+  
+  now=time(NULL);
+  
+  
+  gmtime_r(&now,&crud);
+  
+  then=mkgmtime(&crud);
+  
+  printf("%d %d",now,then);  
+  printf("Hello World!\n");
+}
+*/
+

File diff suppressed because it is too large
+ 16597 - 0
busunit/DIUv2/mongoose.c


File diff suppressed because it is too large
+ 6754 - 0
busunit/DIUv2/mongoose.h


+ 76 - 0
busunit/DIUv2/touchscreen.c

@@ -0,0 +1,76 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "touchscreen.h"
+
+static int ts_calib_left = 0x07F;
+static int ts_calib_right = 0x3BD;
+static int ts_calib_top = 0x040;
+static int ts_calib_bottom = 0x3AA;
+
+void begin_touchscreen_calibration(void) {
+}
+
+void draw_touchscreen_calibration(void) {
+}
+
+int advance_touchscreen_calibration(int raw_x, int raw_y, int down) {
+  return 0;
+}
+
+int translate_ts_x(unsigned rawx)
+{
+    int accum = (rawx - ts_calib_left);
+
+    if(accum < 0)
+        accum = 0;
+
+    accum *= (XRES - 1);
+
+    accum /= (ts_calib_right - ts_calib_left);
+
+    if(accum >= XRES)
+    {
+        return XRES - 1;
+    }
+
+    return accum;
+}
+
+int translate_ts_y(unsigned rawy)
+{
+    int accum = (rawy - ts_calib_top);
+
+    if(accum < 0)
+        accum = 0;
+
+    accum *= (YRES - 1);
+
+    accum /= (ts_calib_bottom - ts_calib_top);
+
+    if(accum >= YRES)
+    {
+        return YRES - 1;
+    }
+
+    return accum;
+}
+
+

+ 37 - 0
busunit/DIUv2/touchscreen.h

@@ -0,0 +1,37 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _TOUCHSCREEN_H
+#define _TOUCHSCREEN_H
+
+#define XRES  (640)
+#define YRES  (480)
+
+#define PIXELS  (XRES * YRES)
+
+
+void begin_touchscreen_calibration(void);
+void draw_touchscreen_calibration(void);
+int advance_touchscreen_calibration(int raw_x, int raw_y, int down);
+
+int translate_ts_x(unsigned rawx);
+int translate_ts_y(unsigned rawy);
+
+#endif

+ 2 - 2
busunit/commhub/commhub.h

@@ -20,8 +20,8 @@
 
 
 //Check to make sure we haven't already defined these things
-#ifndef _TCAT_COMMHUB_API
-#define _TCAN_COMMHUB_API	(1)
+#ifndef _COMMHUB_API
+#define _COMMHUB_API	(1)
 
 #define MSG_NO_ACTION	(0)
 #define MSG_ERROR	(-1)

+ 6 - 0
busunit/common/common_defs.c

@@ -388,7 +388,9 @@ int open_rs232_device(char *devname, int custom_baud, int linemode)
     
     if(fd < 0)
     {
+#ifdef COMMON_PRINT_WARNING
         fprintf(stderr, "Warning:  Cannot open TTY %s\n", devname);
+#endif
         return -1;
     }
     
@@ -397,7 +399,9 @@ int open_rs232_device(char *devname, int custom_baud, int linemode)
     
     if(retval)
     {
+#ifdef COMMON_PRINT_WARNING
         fprintf(stderr, "Warning:  Cannot get TTY attributes on %s.  Not a TTY?\n", devname);
+#endif
         close(fd);
         return -1;
     }
@@ -442,7 +446,9 @@ int open_rs232_device(char *devname, int custom_baud, int linemode)
     
     if(retval)
     {
+#ifdef COMMON_PRINT_WARNING
         fprintf(stderr, "Warning:  Cannot set TTY attributes on %s. Unsupported mode?\n", devname);
+#endif
         close(fd);
         return -1;
     }

+ 1 - 0
busunit/common/common_defs.h

@@ -23,6 +23,7 @@
 #ifndef _COMMON_DEFS
 #define _COMMON_DEFS
 
+//#define COMMON_PRINT_WARNING
 
 //------------------------------- PROCESS DEATH MANAGEMENT ----------------------