mv to attic
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 1 Jul 2014 22:00:25 +0000 (22:00 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 1 Jul 2014 22:00:25 +0000 (22:00 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1726 01035d8c-6547-0410-b346-abe4f91aad63

33 files changed:
attic/.gitignore [deleted file]
attic/dilimesh/README.txt [new file with mode: 0644]
attic/dilimesh/cgi-bin/addnode.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/cleardb.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/delnode.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/fpingnodes.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/getnodes.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/getsig.cgi [new file with mode: 0755]
attic/dilimesh/cgi-bin/getvis.cgi [new file with mode: 0755]
attic/dilimesh/dilimesh/dilimesh.css [new file with mode: 0644]
attic/dilimesh/dilimesh/dilimesh.html [new file with mode: 0644]
attic/dilimesh/dilimesh/node_dead.png [new file with mode: 0644]
attic/dilimesh/dilimesh/node_good.png [new file with mode: 0644]
attic/dilimesh/dilimesh/node_packet_loss.png [new file with mode: 0644]
attic/dilimesh/dilimesh_screenshot.png [new file with mode: 0644]
attic/dilimesh/scripts/S99sigstr [new file with mode: 0755]
attic/dilimesh/scripts/sigstr.sh [new file with mode: 0755]
dilimesh/README.txt [deleted file]
dilimesh/cgi-bin/addnode.cgi [deleted file]
dilimesh/cgi-bin/cleardb.cgi [deleted file]
dilimesh/cgi-bin/delnode.cgi [deleted file]
dilimesh/cgi-bin/fpingnodes.cgi [deleted file]
dilimesh/cgi-bin/getnodes.cgi [deleted file]
dilimesh/cgi-bin/getsig.cgi [deleted file]
dilimesh/cgi-bin/getvis.cgi [deleted file]
dilimesh/dilimesh/dilimesh.css [deleted file]
dilimesh/dilimesh/dilimesh.html [deleted file]
dilimesh/dilimesh/node_dead.png [deleted file]
dilimesh/dilimesh/node_good.png [deleted file]
dilimesh/dilimesh/node_packet_loss.png [deleted file]
dilimesh/dilimesh_screenshot.png [deleted file]
dilimesh/scripts/S99sigstr [deleted file]
dilimesh/scripts/sigstr.sh [deleted file]

diff --git a/attic/.gitignore b/attic/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/attic/dilimesh/README.txt b/attic/dilimesh/README.txt
new file mode 100644 (file)
index 0000000..3f8bc56
--- /dev/null
@@ -0,0 +1,292 @@
+README.txt for dilimesh
+David Rowe
+Dec 7 2010
+
+
+Introduction
+------------
+
+Simple mesh network mapping application (web app) used as a test bed
+for link debugging techniques in the Dili Village Telco.
+
+* Screen shot: dilimesh_screenshot.png
+
+* Currently displays packet loss stats as an alternative to batman
+  scores.  The purpose of this project is to experiment with the
+  display of different information, for example display signal
+  strength or even a spectrum of local Wifi activity for each nodes.
+  The goal is gather information to debug problem links.
+
+* Based on Google maps V3 API.
+
+* Light weight: On the server we have just a few CGIs and a text file
+  database.  A browser cookie is used for storing configuration
+  information.  The CGIs are a few lines of shell script, so can run
+  on any machine.  Installation involves copying a few files and
+  setting a few permissions.
+
+* Loosely coupled design: Can work without any additional software on
+  each mesh mode, just needs a Visualisation server somewhere in the
+  mesh.  Doesn't affct Mesh Potato operation, or the operation of
+  other software on the mesh.
+
+
+Using Dilimesh
+--------------
+
+1/ Point your browser at http://server/dilimesh/dilimesh/html
+
+2/ Set "Visualisation Server IP" on RHS and reload page.
+
+3/ Dilimesh will find new nodes automatically.  Drag bouncing nodes
+   to the correct position on map.
+
+4/ Mouse over or click on a node to get IP and packet loss.  If nodes
+   are running signal strength daemon signal strengths of adjacent
+   nodes will also be displayed.
+
+5/ Click on links to get "Distance" stats on lower right hand side.
+
+5/ Node colours:
+     * blue  - packet loss < 10%
+     * red   - packet loss between 10% and 90%
+     * black - packet loss > 90%
+
+5/ "Update Enable" will update packet loss, network links and signal
+    strength automatically.
+
+
+Status
+------
+
+* Alpha
+* Tested on Firefox 3.5.3 with Apache2 servers running Ubuntu 9 & 10.
+* Tested on small 5 node mesh network, might needs tweaks (e.g. fping
+  arguments) for larger networks
+
+
+Implementation Notes
+--------------------
+
+Dilimesh is implemented in Javascript (dilimesh.html).  A simple text
+database file /var/www/dilimesh/nodes.txt is used to store node
+locations and IPs.  Browser cookies are used to store config
+information like our last map location and vis server IP.  Very simple
+1 page CGIs written in shell script are used to access the node
+database.
+
+The 'Set' buttons on the RHS cause dilimesh.html to reload with CGI
+type variables passed to it.  However these variables are not used, we
+use onclick() methods to change the state variables which are stored
+in a cookie when the page exits.
+
+All the CGI scripts assume a hard coded path of /var/www/dilimesh for
+the nodes.txt database.
+
+
+Directories
+-----------
+
+"dilimesh" directory:
+
+  dilimesh.html        - all the Javascript for Dilimesh
+  dilimesh.css         - style sheet
+  node_good.png        
+  node_packet_loss.png 
+  node_dead.png        - node icon PNGs, changes with packet loss
+
+"cgi-bin" directory:
+
+  addnode.cgi    - adds a node to nodes.txt
+  delnode.cgi    - deletes a node from nodes.txt
+  getnodes.cgi   - reads nodes.txt database
+  getvis.cgi     - reads vis server data
+  fpingnodes.cgi - fires off pings for all nodes, returns results
+  getsig.cgi     - reads signal strength of surrounding nodes from one node,
+                   requires sigstr.sh telnet daemon running on node.
+
+"scripts" directory:
+  
+  sigstr.sh      - script that runs on MP as a telnet daemon to return signal
+                   strength of each node to getsig.cgi.  Experimental.
+  S99sigstr      - /etc/init.d Mesh Potato start upscript for sigstr.sh telnet
+                   daemon
+
+Software
+--------
+
+You need:
+
+1/ A web server. Apache is assumed in the /usr/lib/cgi-bin path below.
+   The paths may be different for other web servers.  Note the path
+   to /var/www/dilimesh is hard coded in the CGI scripts so it's
+   best not to change that.
+
+2/ netcat (nc) and fping installed on the server.  Note that on Ubuntu
+   we found that netcat 1.10.38 was required, netcat-openbsd would not
+   work.
+
+3/ A Batman mesh network with the vis server on one of the nodes, this
+   may already be running on your supernode.  Batman on each node should
+   be configured for the vis server (e.g. -s 10.130.1.1)
+
+4/ A route from the web server PC to the mesh network.  On the Ubuntu
+   machine I use as a server I put this script in the file
+   /etc/network/if-up.d/potato:
+
+     !/bin/sh
+     # Add interface and routes to connect to potato mesh network
+
+     ifconfig eth0 10.30.1.3 netmask 255.255.255.0
+     route add -net 10.130.1.0/24 gw 10.30.1.1
+
+   This file runs when the machine boots and connects to the Supernode
+   via Ethernet.
+
+Installation
+------------
+
+1/ Server PC
+
+  $ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/dilimesh
+  $ cd dilimesh
+  $ sudo mkdir /var/www/dilimesh
+  $ sudo chmod 777 /var/www/dilimesh
+  $ cp dilimesh/* /var/www/dilimesh
+  $ sudo cp cgi-bin/* /usr/lib/cgi-bin
+
+2/ Supernode
+
+  Configure vis server to work on Wifi and Ethernet interfaces:
+
+    # root@OpenWrt:~# cat /etc/config/vis 
+    config vis general
+         option 'interface' 'ath0 eth0'
+
+  If it's running OK you should see a process like:
+
+    # ps | grep vis
+    711 root      1508 S    vis -j ath0 eth0
+
+3/ Batman nodes
+
+  Configure you nodes to use the visualisation server:
+  
+    # cat /etc/config/batman  
+    config batmand general
+        option interface                ath0
+        option announce
+        option gateway_class
+        option originator_interval
+        option preferred_gateway
+        option routing_class
+        option visualisation_srv        10.130.1.1
+        option policy_routing_script
+
+  When batman is running with the vis server it should look like:
+
+    # ps | grep batman
+    552 root      1564 S    batmand -s 10.130.1.1 ath0
+
+4/ (Optional) Signal strength daemon:
+
+  Copy these scripts to each MP in your mesh that you wish to read sig
+  strength from:
+  
+    $ cd dilimesh/script
+    $ scp sigstr.sh root@10.130.1.36:/usr/sbin
+    $ scp S99sigstr  root@10.130.1.36:/etc/rc.d
+  
+  Now start daemon on remote machine:
+
+    $ ssh root@10.130.1.36 '/etc/rc.d/S99sigstr'
+
+  Test if daemon is running
+
+   $ telnet 10.130.1.36 4950
+
+Tests
+-----
+
+1/ Server PC can reach node with vis server:
+
+    $ ping 192.168.1.100
+
+2/ Server PC has route to mesh nodes:
+    $ ping 10.130.1.1
+    $ ping 10.130.1.2
+
+3/ Test you have installed fping:
+
+    $ fping 10.130.1.1
+
+4/ Test netcat and vis server:
+
+    $ nc 192.168.1.100 2005
+
+      HTTP/1.0 200 OK
+      Content-type: application/json
+
+      [
+       { router : "10.130.1.1", neighbour : "10.130.1.23", label : 1.02 },
+       { router : "10.130.1.14", neighbour : "10.130.1.56", label : 1.76 }
+      ]
+
+5/ Test CGIs:
+   Point your browser at: 
+
+     http://localhost/cgi-bin/fpingnodes.cgi?ip=10.130.1.1
+
+6/ Test reading and writing nodes.txt database with your browser:
+
+   http://localhost/cgi-bin/addnode.cgi?lat=123&lng=456&ip=10.130.1.1
+
+   $ cat /var/www/dilimesh/nodes.txt
+   123,456,10.130.1.1
+
+   http://localhost/cgi-bin/delnode.cgi?lat=123&lng=456&ip=10.130.1.1
+
+   $ cat /var/www/dilimesh/nodes.txt
+   (empty file)
+
+7/ Test signal strength daemon on each node:
+
+   $ telnet 10.130.1.1 4950
+   Trying 10.130.1.36...
+   Connected to 10.130.1.36.
+   Escape character is '^]'.
+
+   10.130.1.1 10.130.1.56 10.130.1.14
+   -64 -90 -75
+
+
+Debugging
+---------
+
+1/ Monitor Apache log:
+
+  $ tail -f /var/log/apache2/access.log
+
+2/ Use Firebug on Firefox to single step, set breakpoints etc.
+
+3/ Check nodes.txt database, each line is (lat, lng, IP):
+
+  # cat /var/www/dilimesh/nodes.txt 
+
+  -34.88548650005714,138.55225324630737,10.130.1.56
+  -34.88006501016277,138.55394840240479,10.130.1.1
+  -34.87893842193011,138.55278968811035,10.130.1.23
+  -34.882511765792316,138.55210304260254,10.130.1.14
+  -34.880364257566484,138.5518455505371,10.130.1.36
+
+4/ The "dilimesh" cookie stores a lot of our state. On Firefox 3.5 you
+   can remove the dilimesh cookie using Edit-Preferences-Privacy, then
+   click on "remove individual cookies".
+
+5/ To reset to defaults:
+   
+   * move to another page (cookie is svaed when we exit page)
+   * rm -f /var/www/dilimesh/nodes.txt
+   * Delete cookie using setp (4) above
diff --git a/attic/dilimesh/cgi-bin/addnode.cgi b/attic/dilimesh/cgi-bin/addnode.cgi
new file mode 100755 (executable)
index 0000000..bd78216
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# addnode.cgi
+# David Rowe 4 Dec 2010
+#
+# CGI to add a new node
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head></head>
+<body>
+EOF
+
+lat=`echo "$QUERY_STRING" | sed -n "s/.*lat=\(.*\)&lng.*/\1/p"`
+lng=`echo "$QUERY_STRING" | sed -n "s/.*lng=\(.*\)&ip.*/\1/p"`
+ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=\(.*\)/\1/p"`
+
+echo $lat,$lng,$ip >> /var/www/dilimesh/nodes.txt
+
+echo $QUERY_STRING "<br>"
+echo "<br>"
+echo $lat $lng $ip
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/cleardb.cgi b/attic/dilimesh/cgi-bin/cleardb.cgi
new file mode 100755 (executable)
index 0000000..fa4433c
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+# cleardb.cgi
+# David Rowe 15 Dec 2010
+#
+# CGI to delete entire node database
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head></head>
+<body>
+EOF
+
+# path to node database text file
+
+P=/var/www/dilimesh
+rm $P/nodes.txt
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/delnode.cgi b/attic/dilimesh/cgi-bin/delnode.cgi
new file mode 100755 (executable)
index 0000000..5c8b115
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/sh
+# delnode.cgi
+# David Rowe 4 Dec 2010
+#
+# CGI to delete a node
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head></head>
+<body>
+EOF
+
+lat=`echo "$QUERY_STRING" | sed -n "s/lat=\(.*\)&.*/\1/pg"`
+lng=`echo "$QUERY_STRING" | sed -n "s/.*lng=\(.*\)/\1/pg"`
+
+# path to node database text file
+
+P=/var/www/dilimesh
+
+cat $P/nodes.txt | sed "/$lat,$lng.*/ d" > $P/nodes.tmp
+cp $P/nodes.tmp $P/nodes.txt
+rm $P/nodes.tmp
+
+#echo $QUERY_STRING "<br>"
+#echo "<br>"
+#echo $lat $lng
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/fpingnodes.cgi b/attic/dilimesh/cgi-bin/fpingnodes.cgi
new file mode 100755 (executable)
index 0000000..d0c19fa
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+# fpingnodes.cgi
+# David Rowe 5 Dec 2010
+#
+# CGI to fping a bunch of nodes
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head></head>
+<body>
+EOF
+
+ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p" | sed "s/,/ /g"`
+fping $ip -a -b1400 -r1 2>/dev/null
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/getnodes.cgi b/attic/dilimesh/cgi-bin/getnodes.cgi
new file mode 100755 (executable)
index 0000000..7312089
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+# getnodes.cgi
+# David Rowe 5 Dec 2010
+#
+# CGI to return node list from database text file
+# We use a CGI rather than fetching the text file directly
+# so we can control Firefox from caching
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1">
+</head>
+<body>
+EOF
+
+NODES=/var/www/dilimesh/nodes.txt
+
+if [ -f $NODES ] ; then 
+  cat $NODES
+fi
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/getsig.cgi b/attic/dilimesh/cgi-bin/getsig.cgi
new file mode 100755 (executable)
index 0000000..1850fcc
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/sh
+# getsig.cgi
+# David Rowe 6 Dec 2010
+#
+# CGI to fetch the signal strength from a node
+# Requires the node to be running sigstr.sh script as 
+# a telnet dameon port 4950
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head></head>
+<body>
+EOF
+
+ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p" | sed "s/,/ /g"`
+nc $ip 4950
+echo $ip
+
+cat <<EOF
+</body>
+</html>
+EOF
diff --git a/attic/dilimesh/cgi-bin/getvis.cgi b/attic/dilimesh/cgi-bin/getvis.cgi
new file mode 100755 (executable)
index 0000000..a8723b7
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+# getvis.cgi
+# David Rowe 4 Dec 2010
+#
+# CGI to fetches vis server data
+# I am sure it is possible to do this directly from Javascript
+# but I am too much of a noob.
+
+cat <<EOF
+Content-type: text/html
+
+<html>
+<head>
+<meta http-equiv="cache-control" content="no-cache">
+<meta http-equiv="pragma" content="no-cache">
+<meta http-equiv="expires" content="-1"></head>
+<body>
+EOF
+
+VIS_SERVER_HOST=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p"`
+
+nc $VIS_SERVER_HOST 2005 2>/dev/null >/dev/null 
+if [ $? -eq 0 ] ; then
+  nc $VIS_SERVER_HOST 2005 | sed -n "/{/ p" 
+else
+  echo "Can't connect to Visualisation Server on $VIS_SERVER_HOST"
+fi
+
+cat <<EOF
+</body>
+</html>
+EOF
+
diff --git a/attic/dilimesh/dilimesh/dilimesh.css b/attic/dilimesh/dilimesh/dilimesh.css
new file mode 100644 (file)
index 0000000..d72344f
--- /dev/null
@@ -0,0 +1,70 @@
+html,body{
+       margin:0;
+       padding:0;
+       width:100%;
+       height:100%;
+       font-family:Arial, Helvetica, sans-serif;
+}
+
+div#header{    
+       vertical-align:middle;
+       border-bottom:1px solid #000;
+}
+div#main-map{
+       width:70%;
+       height:100%;
+       float:left;
+}
+div#side{
+       width:30%;
+       float:left;
+}
+
+div#dataPanel{
+       width:90%;
+       height:50%;
+       overflow:auto;
+       border:2px solid #DDDDDD;
+}
+input{
+       width:90%;
+}
+
+input.navi{
+       font-size:12px;
+       height:30px;
+       margin-bottom:10px;
+}
+div ul{
+       margin-top:30px;
+       margin-bottom:30px;
+}
+div ul li{
+       display: inline;
+       list-style-type: none;
+       padding-right: 40px;
+       font-size:18px;
+       font-weight:bold;
+}
+
+div ul li.title{
+       font-size:22px;
+       color:#888;
+}
+
+div#header p{
+       color:#888;
+       font-size:14px;
+       padding-left:20px;
+}
+span.instruction{
+       font-weight:bold;
+       
+}
+
+.message-box { text-align: center; padding: 5px; color:#545454; width:80%;  margin:5px auto; font-size:12px;}
+.clean { background-color: #efefef; border-top: 2px solid #dedede; border-bottom: 2px solid #dedede; }
+.info  { background-color: #f7fafd; border-top: 2px solid #b5d3ff; border-bottom: 2px solid #b5d3ff; }
+.ok    { background-color: #d7f7c4; border-top: 2px solid #82cb2f; border-bottom: 2px solid #82cb2f; }
+.alert { background-color: #fef5be; border-top: 2px solid #fdd425; border-bottom: 2px solid #fdd425; }
+.error { background-color: #ffcdd1; border-top: 2px solid #e10c0c; border-bottom: 2px solid #e10c0c; }
\ No newline at end of file
diff --git a/attic/dilimesh/dilimesh/dilimesh.html b/attic/dilimesh/dilimesh/dilimesh.html
new file mode 100644 (file)
index 0000000..1c00229
--- /dev/null
@@ -0,0 +1,996 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+<style type="text/css">
+  html { height: 100% }
+  body { height: 100%; margin: 0px; padding: 0px }
+  #map_canvas { height: 100% }
+</style>
+<title>Dili Mesh</title>
+
+<link rel="stylesheet" type="text/css" href="dilimesh.css">
+<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
+
+<script type="text/javascript">
+  /*
+     dilimesh.html
+     David Rowe 
+     Dec 4 2010
+
+     Simple mesh network mapping application used as a test bed for debugging
+     problem links in the Dili Village Telco.  
+
+     See dilimesh README.txt for more information.
+  */
+
+  var map;
+
+  // cookie params
+
+  var cookiename = "dilimesh0001";
+  var cookieexpy = 7;
+
+  // these are stored in cookie, with default values
+
+  var lat = 0;
+  var lng = 0;
+  var myzoom = 2;
+  var vis_server_ip = "192.168.1.100";
+  var update_enable = 0;
+  var update_time = 5;
+  var debug_enable  = 0;  
+  var known_location = true;
+
+  // state variables we use while dragging
+
+  var dragIp;
+  var drag_packet_loss;
+  var drag_in_progress;
+  // pathes, vis server data, node list
+
+  var pathes = []; // array of lines, used to delete them
+  var vis    = []; // array of vis server information
+  var nodes  = []; // database of nodes we keep in memory
+                   // mirrors nodes.txt but also store marker locations
+
+  // states for polling sig strength
+
+  var sigstr_node_index = 0;
+
+  // Called when we load page
+
+  function initialize() {
+
+    // we use our cookie as a mini-databse for map location, 
+    // control panel values etc
+    getCookie();
+
+    var myLatlng = new google.maps.LatLng(lat, lng);
+    var myOptions = {
+      zoom: myzoom,
+      center: myLatlng,
+      scaleControl: true,
+      mapTypeId: google.maps.MapTypeId.ROADMAP
+    }
+    map = new google.maps.Map(document.getElementById("main-map"), myOptions);
+
+    // we don't want manual placement of nodes, use vis server to pop
+    // them up
+    //google.maps.event.addListener(map, 'click', function(event) {
+    //  placeMarker(event.latLng);
+    //});
+
+    // set up initial form values
+
+    document.control_panel.vis_server_ip.value = vis_server_ip;
+    document.control_panel.update_time.value = update_time;
+    document.control_panel.update_enable.checked = update_enable;
+    document.control_panel.debug_enable.checked = debug_enable;
+    var html = '<a href="/cgi-bin/getvis.cgi?ip=' + vis_server_ip + ' ">Test Vis Server Connection</a>';
+    document.getElementById('test_vis_server').innerHTML = html;
+
+    // read from nodes.txt database text file on server and init map
+    
+    downloadUrl("/cgi-bin/getnodes.cgi", processMarkers);
+  }
+
+
+  // Slurp up nodes.txt when web pages loads
+
+  processMarkers = function(doc, status) {
+    log("processMarkers");
+
+    // split the document into lines
+
+    var lines = doc.split("\n");
+    for (var i=0; i<lines.length; i++) {
+      if (lines[i].length > 1) {
+
+        // split each line into parts separated by "," and use the contents
+
+        parts = lines[i].split(",");
+        if (parts.length > 1) {
+          var lat = parseFloat(parts[0]);
+          var lng = parseFloat(parts[1]);
+          var ip = parts[2];
+          if (ip == undefined) {
+            ip = "";
+          }
+
+          // sanity check, make sure no duplicate IPs
+   
+          if (dupIp(ip))
+            log("Error - Duplicate IP " + ip + " in nodes.txt");
+          else
+            addNewNode(lat, lng, ip, false);
+        }
+      }
+    }
+
+    // initial map display, only if we have a sensible map location.  Otherwise
+    // new nodes will be placed in middle of current default location
+    if (known_location)
+      poll();       
+
+    // kick off timer process that periodically fires off vis and fping CGIs
+
+    timer();
+  }
+
+
+  // check for duplicate IPs
+
+  function dupIp(ip) {
+
+    if ( (ip == undefined) || (ip == ""))
+      return false;
+
+    // walk nodes list looking for this IP
+
+    for (var j=0; j<nodes.length; j++) {
+        if (nodes[j].ip == ip) {
+          return true;
+        }
+      }
+
+    return false;
+
+  }
+
+
+  // Process the Vis server information 
+
+  processVis = function(doc, status) {
+    log("processVis");
+
+    if (drag_in_progress)
+      return;
+
+    // extract the JSON lines from doc returned by getvis.cgi
+    // there is surely a better way to do this but I am a JSON noob
+
+    var lines = doc.split("\n");
+    var vis_str = "vis = {data: [\n";
+    for (var i=0; i<lines.length; i++) {
+      if (lines[i].length > 1) {
+        if (lines[i].indexOf('{') != -1) {
+          vis_str = vis_str + lines[i] + "\n";
+        }
+      }
+    }
+    
+    vis_str = vis_str + "]\n};"
+    eval(vis_str); // run time compilation of JSON string
+    
+    // OK now we have an array that we can parse for new nodes
+
+    // walk vis list by router
+
+    var new_nodes = 0;
+    for (var i=0; i<vis.data.length; i++) {
+
+      // see if this node exists in our database
+      var node_exists = 0;
+      for (var j=0; j<nodes.length; j++) {
+        if (vis.data[i].router == nodes[j].ip) {
+          node_exists = 1;
+        }
+      }    
+
+      // create node if it doesn't exists already
+
+      if (node_exists == 0) {
+         // small offset makes sure we don't create them all on one spot
+         var location = new google.maps.LatLng(lat + 1E-4*nodes.length, lng);
+         placeMarker(location, vis.data[i].router, true);
+      }
+    }
+
+    // walk vis list by neighbour
+
+    for (var i=0; i<vis.data.length; i++) {
+
+      if (vis.data[i].neighbour != undefined) {
+
+        // see if this node exists in our database
+        var node_exists = 0;
+        for (var j=0; j<nodes.length; j++) {
+          if (vis.data[i].neighbour == nodes[j].ip) {
+            node_exists = 1;
+          }
+        }    
+
+        // create node if it doesn't exists already
+
+        if (node_exists == 0) {
+          // small offset makes sure we don't create them all on one spot
+          var location = new google.maps.LatLng(lat + 1E-4*nodes.length, lng);
+          placeMarker(location, vis.data[i].neighbour, true);
+        }
+      }
+    }
+
+    // now all nodes are logged in text file and nodes database
+    // lets see if we any have routes between them
+
+    drawPathesBetweenNodes();
+  }
+
+  function poll() {
+
+    // fire off vis server CGI
+
+    downloadUrl("/cgi-bin/getvis.cgi?ip=" + vis_server_ip, processVis);
+    // fire off fping CGI
+
+    var ips = "ip=";
+    for (var j=0; j<nodes.length; j++) {
+      if (nodes[j].ip != "") {
+        ips = ips + nodes[j].ip;
+        if (j != (nodes.length-1)) {
+          ips = ips + ",";
+        }
+      }
+    }    
+                                                 
+    if (ips != "") {
+      downloadUrl("/cgi-bin/fpingnodes.cgi?" + ips, processFping);
+
+      // set up HTML for manual ping test
+    
+      var html = '<a href="/cgi-bin/fpingnodes.cgi?' + ips + ' ">Ping nodes</a>';
+      document.getElementById('ping_nodes').innerHTML = html;
+    }
+
+    // fire off next sig strength CGI, we iterate these over time to keep
+    // network load nominal
+
+    if (nodes[sigstr_node_index] != undefined) {
+      downloadUrl("/cgi-bin/getsig.cgi?ip=" + nodes[sigstr_node_index].ip, processgetSig);
+      document.getElementById('sigstr_current_node').innerHTML = nodes[sigstr_node_index].ip;
+    }
+    sigstr_node_index++;
+    if (sigstr_node_index >= nodes.length)
+      sigstr_node_index = 0;
+  }
+
+
+  // this function calls itself every update_time seconds
+  // used for peridoic updates (polling) of network stats
+
+  function timer() {
+    var today=new Date();
+    var h=today.getHours();
+    var m=today.getMinutes();
+    var s=today.getSeconds();
+
+    // set time, add a zero in front of numbers < 10
+
+    m=checkTime(m);
+    s=checkTime(s);
+    document.getElementById('time').innerHTML=h+":"+m+":"+s;
+
+    if (update_enable)
+      poll();
+
+    // restart this timer after update_time seconds
+   
+    t=setTimeout('timer()',update_time*1000);
+  }
+
+
+  function checkTime(i) {
+    if (i<10) {
+      i="0" + i;
+    }
+    return i;
+  }
+
+
+  // called when Fping CGI returns
+
+  function processFping(doc, status) {
+
+    //log("processFping");
+
+    if (drag_in_progress)
+      return;
+
+    // walk node list and set colour depending on ping stats
+
+    var nodes_reachable = 0;
+    var nodes_poor_packet_loss = 0;
+    for (var j=0; j<nodes.length; j++) {
+      if (doc.indexOf(nodes[j].ip) == -1) {
+        // no ping from node
+        nodes[j].marker.setIcon("node_dead.png");
+        // update IIR averaging filter
+        nodes[j].packet_loss = 0.875*nodes[j].packet_loss + 0.125;
+      }
+      else {
+
+        // update IIR averaging filter
+
+        nodes[j].packet_loss = 0.875*nodes[j].packet_loss;
+        nodes_reachable++;
+      }
+
+      // Change icon based on packet loss
+
+      if (nodes[j].packet_loss < 0.1) {
+           nodes[j].marker.setIcon("node_good.png");
+      }
+      if ((nodes[j].packet_loss > 0.1) && (nodes[j].packet_loss < 0.9)) {
+        nodes[j].marker.setIcon("node_packet_loss.png");
+        nodes_poor_packet_loss++;
+      }
+      if (nodes[j].packet_loss > 0.9) {
+        nodes[j].marker.setIcon("node_dead.png");
+        nodes_poor_packet_loss++;
+      }
+                                                 
+      //log("  nodes[j].packet_loss");
+
+      var packet_loss_formatted = Math.round(nodes[j].packet_loss*100);
+
+      nodes[j].marker.setTitle(nodes[j].ip + ' Packet Loss: ' + packet_loss_formatted + '%');  
+      var html  = '<table>';
+          html += '<tr><th>' + nodes[j].ip + '</th></tr>';
+          html += '<tr><td>Packet Loss</td><td>' + packet_loss_formatted + '%</td></tr>';
+      if (nodes[j].neighbour_ips != undefined) {
+        for(var i=0; i<nodes[j].neighbour_ips.length; i++) {
+          html += '<tr><td>' + trim(nodes[j].neighbour_ips[i]) + '</td><td>';
+          html += trim(nodes[j].neighbour_sigs[i]) + ' dBm</td><td>';
+       }
+      }
+      html += '</table>';
+
+      nodes[j].infowindow.setContent(html);  
+    }  
+
+    document.getElementById('nodes_total').innerHTML = nodes.length;
+    document.getElementById('nodes_reachable').innerHTML = nodes_reachable;  
+    document.getElementById('nodes_poor_packet_loss').innerHTML = nodes_poor_packet_loss;  
+  }
+
+
+  // remove leading and trailing whitespace from a string
+
+  function trim(stringToTrim) {
+       return stringToTrim.replace(/^\s+|\s+$/g,"");
+  }
+
+
+  // called when getsig.cgi returns to grok signal
+  // strength information
+
+  function processgetSig(doc, status) {
+    log("processgetSig");
+   
+    // extract our lines from the HTML using state machine
+   
+    var lines = doc.split("\n");
+    var ip;
+    var neighour_ips;
+    var neighour_sigs
+    var state = "start";
+    var next_state;
+    for (var j=0; j<lines.length; j++) {
+
+      next_state = state;
+      if (state == "start") {
+        if (lines[j].indexOf('sigstr') != -1)
+          next_state = "read ips";
+      }
+      if (state == "read ips") {
+        neighbour_ips = lines[j].split(" ");
+        next_state = "read sigs";
+      }
+      if (state == "read sigs") {
+        neighbour_sigs = trim(lines[j]).split(" ");
+        next_state = "read ip";
+      }
+      if (state == "read ip") {
+        ip =lines[j];
+        next_state = "finished";
+      }
+      state = next_state;
+    }
+
+    if (state == "finished") {
+     // walk nodes list to match ip
+
+      for (var j=0; j<nodes.length; j++) {
+        if (nodes[j].ip == ip) {
+          nodes[j].neighbour_ips  = neighbour_ips;
+          nodes[j].neighbour_sigs = neighbour_sigs;
+          var html="<table>";
+          for(var i=0; i<neighbour_ips.length; i++) {
+            html += '<tr><td>' + trim(neighbour_ips[i]) + '</td><td>' + trim(neighbour_sigs[i]) + ' dBm</td></tr>';
+          }
+          html += '</table>';
+         document.getElementById('sigstr_last_node').innerHTML = ip;
+         document.getElementById('sigstr_results').innerHTML = html;
+        }    
+      }
+    }
+  }
+
+
+  // calculate distance between two points
+
+  rad = function(x) {return x*Math.PI/180;}
+
+  distHaversine = function(p1, p2) {
+    var R = 6371; // earth's mean radius in km
+    var dLat  = rad(p2.lat() - p1.lat());
+    var dLong = rad(p2.lng() - p1.lng());
+
+    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
+            Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
+    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
+    var d = R * c;
+
+    return d.toFixed(3);
+  }
+
+
+  // draw lines indicating links between nodes 
+
+  function drawPathesBetweenNodes() {
+
+    // delete all existing paths, this is inefficient but is OK for a first pass
+      
+    if (pathes) {
+      for (j in pathes) {
+        pathes[j].setMap(null);
+      }
+      pathes.length = 0;
+    }
+
+    // walk vis array looking for routes, I think this actually draws
+    // routes twice
+
+    for (var i=0; i<vis.data.length; i++) {
+   
+      if (vis.data[i].neighbour != undefined) {
+        // this entry in vis array has a route and a neighbour
+
+        router_ip = vis.data[i].router;
+        neighbour_ip = vis.data[i].neighbour;
+
+        // walk nodes list to find router location on map
+
+        var router_location;
+        for (var j=0; j<nodes.length; j++) {
+          if (router_ip == nodes[j].ip) {
+            router_location = nodes[j].marker.position;
+          }
+        }    
+
+        // walk nodes list to find neighbour location on map
+
+        var neighbour_location;
+        for (var j=0; j<nodes.length; j++) {
+          if (neighbour_ip == nodes[j].ip) {
+            neighbour_location = nodes[j].marker.position;
+          }
+        }    
+
+       if ((router_location != undefined) && (neighbour_location != undefined)) {
+         // draw polyline between locations
+
+          var coords = [
+            router_location,
+            neighbour_location
+          ];
+          var path = new google.maps.Polyline({
+            path: coords,
+            strokeColor: "#008000",
+            strokeOpacity: 0.5,
+            strokeWeight: 5
+          });
+          path.setMap(map);
+
+          // click on line to get distance and path loss estimates
+
+          google.maps.event.addListener(path, "click", function() {
+            var path = this.getPath();
+            var dist = distHaversine(path.b[0], path.b[1]) * 1000;
+
+            // est rx power: 
+            //   MP tx pwr between 15 and 20dB depending on rate, so use 17dB
+            //   roughly 2dB tx and rx antennas
+            //   100dB loss for 1000m, 6dB more for double distance
+
+            var path_loss = 100.0 + 20*Math.log(dist/1000)/Math.log(10);
+            path_loss =  Math.round(path_loss);
+            var est_rx_sig = 17 + 2 + 2 - path_loss;
+
+            document.getElementById('distance').innerHTML = dist + ' m';
+            document.getElementById('path_loss').innerHTML = -path_loss + ' dBm';
+            document.getElementById('est_rx_sig').innerHTML = est_rx_sig + ' dBm';
+          });
+         
+          pathes.push(path);
+        }  
+      }          
+    }
+  }
+
+
+  // sets up map for a new Node
+  // adds node to nodes[] array but doesn't write to text file
+
+  function addNewNode(lat, lng, newIp, isNewNode) {
+
+    // create the marker
+
+    var location = new google.maps.LatLng(lat, lng);
+    var newMarker = new google.maps.Marker(
+      {position: location, 
+       map: map, 
+       draggable: true,
+       title: newIp,
+       icon: "node_good.png" });
+
+    if (isNewNode) {
+      newMarker.setAnimation(google.maps.Animation.BOUNCE);
+    }
+
+    // add to nodes array
+
+    var newInfoWindow = new google.maps.InfoWindow(
+      { content: newIp
+      });
+    var newNode = {marker : newMarker, 
+                   ip: newIp, 
+                   infowindow: newInfoWindow, 
+                   packet_loss: 0.0};
+    nodes.push(newNode); 
+
+    // add listeners
+
+    google.maps.event.addListener(newMarker, "dragstart", function() {
+
+      drag_in_progress = 1;
+
+      // remove node from nodes array
+
+      var new_nodes = [];
+      for (var j=0; j<nodes.length; j++) {
+        if (nodes[j].marker.position != newMarker.position) {
+          new_nodes.push(nodes[j]);
+        }
+        else {
+          // preserve some states for when we drop it
+          dragIp = nodes[j].ip;
+          drag_packet_loss = nodes[j].packet_loss;
+        }
+      }
+      nodes = new_nodes;
+
+      // delete node from text file
+
+      var url;
+      url = "/cgi-bin/delnode.cgi?" + "lat=" + this.position.lat() + "&" + "lng=" +
+             this.position.lng();
+      downloadUrl(url, function(doc) { });
+    });
+
+    google.maps.event.addListener(newMarker, "dragend", function() {
+
+      // stop any bouncing
+      newMarker.setAnimation(null);
+
+      // add node to nodes array
+
+      var newInfoWindow = new google.maps.InfoWindow(
+        {  content: dragIp
+        });
+      var newNode = {marker : newMarker, 
+                     ip: dragIp, 
+                     infowindow: newInfoWindow, 
+                     packet_loss: drag_packet_loss
+      };
+      nodes.push(newNode); 
+     
+      // add node to text file
+
+      var url;
+      url = "/cgi-bin/addnode.cgi?" + "lat=" +  this.position.lat() + "&" + "lng=" +
+            this.position.lng() + "&" + "ip=" + dragIp;
+      downloadUrl(url, function(doc) { });
+
+      drawPathesBetweenNodes();
+
+      drag_in_progress = 0;
+    });
+
+    google.maps.event.addListener(newMarker, "click", function() {
+
+      // walk node list to find our InfoWindow
+
+      for (var j=0; j<nodes.length; j++) {
+        if (nodes[j].marker.position == newMarker.position) {
+          nodes[j].infowindow.open(map, newMarker);
+        }
+      }    
+
+    });
+
+    google.maps.event.addListener(newMarker, "rightclick", function() {
+
+      // remove node from nodes array
+
+      var new_nodes = [];
+      for (var j=0; j<nodes.length; j++) {
+        if (nodes[j].marker.position != newMarker.position) {
+          new_nodes.push(nodes[j]);
+        }
+      }
+      nodes = new_nodes;
+
+      // delete node from text file
+
+      var url;
+      url = "/cgi-bin/delnode.cgi?" + "lat=" +  this.position.lat() + "&" + "lng=" +  this.position.lng();
+      downloadUrl(url, function(doc) { });
+      this.setMap(null);
+
+      drawPathesBetweenNodes();
+
+    });
+
+  }
+
+
+  // save state (config info) to our cookie
+
+  function setCookie() {
+    var cookietext = cookiename;
+    cookietext += "=" + map.getCenter().lat();
+    cookietext += "|" + map.getCenter().lng() + "|" + map.getZoom();
+    cookietext += "|" + vis_server_ip + "|" + update_time;
+    cookietext += "|" + update_enable + "|" + debug_enable;
+    if (cookieexpy) {
+      var exdate=new Date();
+      exdate.setDate(exdate.getDate()+cookieexpy);
+      cookietext += ";expires="+exdate.toGMTString();
+    }
+    
+    // write the cookie
+
+    document.cookie = cookietext;
+  }
+
+
+  // Grab a bunch of config info from our cookie
+
+  function getCookie() {
+                       
+    if (document.cookie.length > 0) {
+      cookieStart = document.cookie.indexOf(cookiename + "=");
+
+      // lets see if our cookie exists
+
+      if (cookieStart!=-1) {
+        cookieStart += cookiename.length+1; 
+        cookieEnd=document.cookie.indexOf(";",cookieStart);
+        if (cookieEnd==-1) {
+          cookieEnd=document.cookie.length;
+        }
+        cookietext = document.cookie.substring(cookieStart,cookieEnd);
+        // split the cookie text and create the variables
+
+        bits = cookietext.split("|");
+        lat = parseFloat(bits[0]);
+        lng = parseFloat(bits[1]);
+        myzoom = parseInt(bits[2]);
+        vis_server_ip = (bits[3]);
+        update_time = parseInt(bits[4]);
+        update_enable = parseInt(bits[5]);
+        debug_enable = parseInt(bits[6]);
+      }
+    } 
+    else {
+      known_location = false; // don't detect and display new nodes
+      alert("Move to your " +
+            "current location then refresh to detect nodes.");              
+
+    }
+
+  }
+
+
+  // clear database and set cookie to defaults
+
+  function clearDatabase() {
+
+    // call CGI to rm nodes.txt
+
+    downloadUrl("/cgi-bin/cleardb.cgi", function(doc) { });
+    nodes = [];    
+
+    // I would really like to clear cookie but can't work out how, so
+    // set to defaults instead, 
+
+    var myLatLng = new google.maps.LatLng(0, 0);
+    map.setCenter(myLatLng);
+    map.setZoom(2);
+    update_enable = 0;                          
+ }
+
+
+  // called when we click to add a node on map
+
+  function placeMarker(location, ip, isNewNode) {
+    if (ip == undefined) {
+      ip = "";
+    }
+    if (isNewNode == undefined) {
+      isNewNode = false;
+    }
+
+    addNewNode(location.lat(), location.lng(), ip, isNewNode);
+
+    // save to marker file by calling a CGI
+
+    var url;
+    url = "/cgi-bin/addnode.cgi?" + "lat=" + location.lat() + "&" + "lng=" + location.lng() + "&" + "ip=" + ip;
+    downloadUrl(url, function(doc) { });
+  }
+  
+  /**
+  * Returns an XMLHttp instance to use for asynchronous
+  * downloading. This method will never throw an exception, but will
+  * return NULL if the browser does not support XmlHttp for any reason.
+  * @return {XMLHttpRequest|Null}
+  */
+  function createXmlHttpRequest() {
+    try {
+      if (typeof ActiveXObject != 'undefined') {
+        return new ActiveXObject('Microsoft.XMLHTTP');
+      } else if (window["XMLHttpRequest"]) {
+        return new XMLHttpRequest();
+      }
+     } catch (e) {
+     changeStatus(e);
+     }
+   return null;
+  };
+
+  /**
+  * This functions wraps XMLHttpRequest open/send function.
+  * It lets you specify a URL and will call the callback if
+  * it gets a status code of 200.
+  * @param {String} url The URL to retrieve
+  * @param {Function} callback The function to call once retrieved.
+  */
+  function downloadUrl(url, callback) {
+    var status = -1;
+    var request = createXmlHttpRequest();
+    if (!request) {
+      return false;
+    }
+
+    request.onreadystatechange = function() {
+      if (request.readyState == 4) {
+        try {
+          status = request.status;
+        } catch (e) {
+          // Usually indicates request timed out in FF.
+        }
+        if (status == 200) {
+          callback(request.responseText, request.status);
+          request.onreadystatechange = function() {};
+        }
+      }
+    }
+    request.open('GET', url, true);
+    try {
+      request.send(null);
+    } catch (e) {
+      changeStatus(e);
+    }
+  };
+
+  function log(message) {
+    if (debug_enable == 1) {
+      message_list = document.getElementById("debugging_messages");
+      log_message = document.createTextNode(message);
+      log_list_item = document.createElement('li');
+      log_list_item.appendChild(log_message);
+      message_list.appendChild(log_list_item);
+    }
+  }
+
+  function debugClicked() {
+    if (document.control_panel.debug_enable.checked)
+      debug_enable = 1;
+    else
+      debug_enable = 0;
+  }
+
+  function updateEnableClicked() {
+    if (document.control_panel.update_enable.checked)
+      update_enable = 1;
+    else
+      update_enable = 0;
+  }
+
+  function setVisServerIp() {
+    vis_server_ip = document.control_panel.vis_server_ip.value;
+    var html = '<a href="/cgi-bin/getvis.cgi?ip=' + vis_server_ip + ' ">Test Vis Server Connection</a>';
+    document.getElementById('test_vis_server').innerHTML = html;
+  }
+
+  function setUpdateTime() {
+    update_time = document.control_panel.update_time.value;
+  }
+
+</script>
+
+</head>
+<body onload="initialize()" onunload="setCookie()">
+
+  <div id="main-map">
+  </div>
+
+  <div id="side">
+
+    <h3>Help</h3>
+      <table>
+        <tr><td width="5%"></td><td><a href="https://freetel.svn.sourceforge.net/svnroot/freetel/dilimesh/README.txt">DiliMesh README</a></td></tr>
+      </table>
+
+    <div id="stats" style="width: 100%;">
+      <h3>Network Stats</h3>
+        <table>
+         <tr><td width="5%"></td><td>Time</td><td><div id="time"></div></td></tr>
+         <tr><td></td><td>Nodes Reachable</td><td><div id="nodes_reachable"></div></td></tr>
+         <tr><td></td><td>Nodes Poor Packet Loss</td><td><div id="nodes_poor_packet_loss"></div></td></tr>
+         <tr><td></td><td>Nodes Total</td><td><div id="nodes_total"></div></td></tr>
+        </table>
+    </div>
+
+    <div id="control" style="width: 100%;">
+      <h3>Contol Panel</h3>
+      <form name="control_panel">
+        <table>
+       <tr>
+          <td width="5%">
+          <td>Visualisation Server IP</td>
+          <td colspan="2"><input type="text" name="vis_server_ip" size="15"></td>
+          <td width="50"><input type="submit" value="Set" onclick="setVisServerIp()"></td>
+        </tr>
+        <tr>
+          <td></td>
+         <td>Update Enable</td>
+          <td><input type="checkbox" name="update_enable" value="1" onclick="updateEnableClicked()"></td>
+        </tr>
+        <tr>
+          <td></td>
+         <td>Update Time (s)</td>
+          <td><input type="text" name="update_time" size="3"></td>
+          <td width="30%"></td>
+          <td width="50"><input type="submit" value="Set" onclick="setUpdateTime()"></td>
+        </tr>
+        <tr>
+          <td></td>
+         <td>Clear Database</td>
+          <td></td>
+          <td width="30%"></td>
+          <td width="60"><input type="submit" value="Clear" onclick="clearDatabase()"></td>
+        </tr>
+        <tr>
+         <td></td>
+          <td>Debug Messages</td>
+          <td><input type="checkbox" name="debug_enable" onclick="debugClicked()"></td>
+        </tr>
+        </table>
+      </form>
+
+      <h3>Signal Strength</h3>
+        <table>
+        <tr>
+         <td width="5%"></td>
+          <td>Currently Polling</td>
+          <td><div id="sigstr_current_node"></div></td>
+        </tr>
+        <tr>
+         <td></td>
+          <td>Last Node that<br>Responded</td>
+          <td><div id="sigstr_last_node"></div></td>
+        </tr>
+        <tr>
+         <td></td>
+          <td valign=top>Results</td>
+          <td><div id="sigstr_results"></div></td>
+        </tr>
+        </table>
+
+      <h3>Distance</h3>
+        <table>
+        <tr>
+         <td width="5%"></td>
+          <td valign=top>Distance</td>
+          <td><div id="distance"></div></td>
+        </tr>
+        <tr>
+         <td></td>
+          <td valign=top>Path Loss</td>
+          <td><div id="path_loss"></div></td>
+        </tr>
+        <tr>
+         <td></td>
+          <td valign=top>Est Rx Signal</td>
+          <td><div id="est_rx_sig"></div></td>
+        </tr>
+        </table>
+    </div>
+
+    <div id="tests" style="width: 100%;">
+      <h3>Tests</h3>
+      <ol>
+       <li><a href="/cgi-bin/getnodes.cgi">Test nodes.txt database</a><br>
+        <li><div id="test_vis_server">&nbsp</div>
+        <li><div id="ping_nodes">&nbsp</div>
+      </ol>
+    </div>
+
+    <div id="debugging_output" style="width: 100%;">
+      <h3>Debugging Output</h3>
+      <ol id="debugging_messages">
+      </ol>
+    </div>
+  </div>
+
+
+</body>
+</html>
diff --git a/attic/dilimesh/dilimesh/node_dead.png b/attic/dilimesh/dilimesh/node_dead.png
new file mode 100644 (file)
index 0000000..88be550
Binary files /dev/null and b/attic/dilimesh/dilimesh/node_dead.png differ
diff --git a/attic/dilimesh/dilimesh/node_good.png b/attic/dilimesh/dilimesh/node_good.png
new file mode 100644 (file)
index 0000000..056f1c9
Binary files /dev/null and b/attic/dilimesh/dilimesh/node_good.png differ
diff --git a/attic/dilimesh/dilimesh/node_packet_loss.png b/attic/dilimesh/dilimesh/node_packet_loss.png
new file mode 100644 (file)
index 0000000..5842080
Binary files /dev/null and b/attic/dilimesh/dilimesh/node_packet_loss.png differ
diff --git a/attic/dilimesh/dilimesh_screenshot.png b/attic/dilimesh/dilimesh_screenshot.png
new file mode 100644 (file)
index 0000000..7c26086
Binary files /dev/null and b/attic/dilimesh/dilimesh_screenshot.png differ
diff --git a/attic/dilimesh/scripts/S99sigstr b/attic/dilimesh/scripts/S99sigstr
new file mode 100755 (executable)
index 0000000..a33f816
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+telnetd -l /usr/sbin/sigstr.sh -p 4950
diff --git a/attic/dilimesh/scripts/sigstr.sh b/attic/dilimesh/scripts/sigstr.sh
new file mode 100755 (executable)
index 0000000..726458a
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+# node_tune.sh
+# David Rowe 13 April 2010
+#
+# Prints information useful for tuning a mesh node
+#
+# Useful to run as a telnet login, e.g.
+#   telnetd -l /usr/sbin/node_tune.sh -p 4950
+# will let you plug a laptop into eth0 and "telnet 192.168.1.20 4950"
+# to run this script
+
+  # list of nodes this node can see in IP and MAC order
+  
+  IP=`cat /proc/net/arp | grep "10.130.1" | awk '{ print $1 }'`
+  MAC=`cat /proc/net/arp | grep "10.130.1" | awk '{ print $4 }'`
+  
+  echo
+  echo "sigstr"
+  echo $IP
+  for m in $MAC
+  do
+    wlanconfig ath0 list | grep $m | awk '{ printf " %s",$6 }'
+  done
+  echo
+
+
+
+
diff --git a/dilimesh/README.txt b/dilimesh/README.txt
deleted file mode 100644 (file)
index 3f8bc56..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-README.txt for dilimesh
-David Rowe
-Dec 7 2010
-
-
-Introduction
-------------
-
-Simple mesh network mapping application (web app) used as a test bed
-for link debugging techniques in the Dili Village Telco.
-
-* Screen shot: dilimesh_screenshot.png
-
-* Currently displays packet loss stats as an alternative to batman
-  scores.  The purpose of this project is to experiment with the
-  display of different information, for example display signal
-  strength or even a spectrum of local Wifi activity for each nodes.
-  The goal is gather information to debug problem links.
-
-* Based on Google maps V3 API.
-
-* Light weight: On the server we have just a few CGIs and a text file
-  database.  A browser cookie is used for storing configuration
-  information.  The CGIs are a few lines of shell script, so can run
-  on any machine.  Installation involves copying a few files and
-  setting a few permissions.
-
-* Loosely coupled design: Can work without any additional software on
-  each mesh mode, just needs a Visualisation server somewhere in the
-  mesh.  Doesn't affct Mesh Potato operation, or the operation of
-  other software on the mesh.
-
-
-Using Dilimesh
---------------
-
-1/ Point your browser at http://server/dilimesh/dilimesh/html
-
-2/ Set "Visualisation Server IP" on RHS and reload page.
-
-3/ Dilimesh will find new nodes automatically.  Drag bouncing nodes
-   to the correct position on map.
-
-4/ Mouse over or click on a node to get IP and packet loss.  If nodes
-   are running signal strength daemon signal strengths of adjacent
-   nodes will also be displayed.
-
-5/ Click on links to get "Distance" stats on lower right hand side.
-
-5/ Node colours:
-     * blue  - packet loss < 10%
-     * red   - packet loss between 10% and 90%
-     * black - packet loss > 90%
-
-5/ "Update Enable" will update packet loss, network links and signal
-    strength automatically.
-
-
-Status
-------
-
-* Alpha
-* Tested on Firefox 3.5.3 with Apache2 servers running Ubuntu 9 & 10.
-* Tested on small 5 node mesh network, might needs tweaks (e.g. fping
-  arguments) for larger networks
-
-
-Implementation Notes
---------------------
-
-Dilimesh is implemented in Javascript (dilimesh.html).  A simple text
-database file /var/www/dilimesh/nodes.txt is used to store node
-locations and IPs.  Browser cookies are used to store config
-information like our last map location and vis server IP.  Very simple
-1 page CGIs written in shell script are used to access the node
-database.
-
-The 'Set' buttons on the RHS cause dilimesh.html to reload with CGI
-type variables passed to it.  However these variables are not used, we
-use onclick() methods to change the state variables which are stored
-in a cookie when the page exits.
-
-All the CGI scripts assume a hard coded path of /var/www/dilimesh for
-the nodes.txt database.
-
-
-Directories
------------
-
-"dilimesh" directory:
-
-  dilimesh.html        - all the Javascript for Dilimesh
-  dilimesh.css         - style sheet
-  node_good.png        
-  node_packet_loss.png 
-  node_dead.png        - node icon PNGs, changes with packet loss
-
-"cgi-bin" directory:
-
-  addnode.cgi    - adds a node to nodes.txt
-  delnode.cgi    - deletes a node from nodes.txt
-  getnodes.cgi   - reads nodes.txt database
-  getvis.cgi     - reads vis server data
-  fpingnodes.cgi - fires off pings for all nodes, returns results
-  getsig.cgi     - reads signal strength of surrounding nodes from one node,
-                   requires sigstr.sh telnet daemon running on node.
-
-"scripts" directory:
-  
-  sigstr.sh      - script that runs on MP as a telnet daemon to return signal
-                   strength of each node to getsig.cgi.  Experimental.
-  S99sigstr      - /etc/init.d Mesh Potato start upscript for sigstr.sh telnet
-                   daemon
-
-Software
---------
-
-You need:
-
-1/ A web server. Apache is assumed in the /usr/lib/cgi-bin path below.
-   The paths may be different for other web servers.  Note the path
-   to /var/www/dilimesh is hard coded in the CGI scripts so it's
-   best not to change that.
-
-2/ netcat (nc) and fping installed on the server.  Note that on Ubuntu
-   we found that netcat 1.10.38 was required, netcat-openbsd would not
-   work.
-
-3/ A Batman mesh network with the vis server on one of the nodes, this
-   may already be running on your supernode.  Batman on each node should
-   be configured for the vis server (e.g. -s 10.130.1.1)
-
-4/ A route from the web server PC to the mesh network.  On the Ubuntu
-   machine I use as a server I put this script in the file
-   /etc/network/if-up.d/potato:
-
-     !/bin/sh
-     # Add interface and routes to connect to potato mesh network
-
-     ifconfig eth0 10.30.1.3 netmask 255.255.255.0
-     route add -net 10.130.1.0/24 gw 10.30.1.1
-
-   This file runs when the machine boots and connects to the Supernode
-   via Ethernet.
-
-Installation
-------------
-
-1/ Server PC
-
-  $ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/dilimesh
-  $ cd dilimesh
-  $ sudo mkdir /var/www/dilimesh
-  $ sudo chmod 777 /var/www/dilimesh
-  $ cp dilimesh/* /var/www/dilimesh
-  $ sudo cp cgi-bin/* /usr/lib/cgi-bin
-
-2/ Supernode
-
-  Configure vis server to work on Wifi and Ethernet interfaces:
-
-    # root@OpenWrt:~# cat /etc/config/vis 
-    config vis general
-         option 'interface' 'ath0 eth0'
-
-  If it's running OK you should see a process like:
-
-    # ps | grep vis
-    711 root      1508 S    vis -j ath0 eth0
-
-3/ Batman nodes
-
-  Configure you nodes to use the visualisation server:
-  
-    # cat /etc/config/batman  
-    config batmand general
-        option interface                ath0
-        option announce
-        option gateway_class
-        option originator_interval
-        option preferred_gateway
-        option routing_class
-        option visualisation_srv        10.130.1.1
-        option policy_routing_script
-
-  When batman is running with the vis server it should look like:
-
-    # ps | grep batman
-    552 root      1564 S    batmand -s 10.130.1.1 ath0
-
-4/ (Optional) Signal strength daemon:
-
-  Copy these scripts to each MP in your mesh that you wish to read sig
-  strength from:
-  
-    $ cd dilimesh/script
-    $ scp sigstr.sh root@10.130.1.36:/usr/sbin
-    $ scp S99sigstr  root@10.130.1.36:/etc/rc.d
-  
-  Now start daemon on remote machine:
-
-    $ ssh root@10.130.1.36 '/etc/rc.d/S99sigstr'
-
-  Test if daemon is running
-
-   $ telnet 10.130.1.36 4950
-
-Tests
------
-
-1/ Server PC can reach node with vis server:
-
-    $ ping 192.168.1.100
-
-2/ Server PC has route to mesh nodes:
-    $ ping 10.130.1.1
-    $ ping 10.130.1.2
-
-3/ Test you have installed fping:
-
-    $ fping 10.130.1.1
-
-4/ Test netcat and vis server:
-
-    $ nc 192.168.1.100 2005
-
-      HTTP/1.0 200 OK
-      Content-type: application/json
-
-      [
-       { router : "10.130.1.1", neighbour : "10.130.1.23", label : 1.02 },
-       { router : "10.130.1.14", neighbour : "10.130.1.56", label : 1.76 }
-      ]
-
-5/ Test CGIs:
-   Point your browser at: 
-
-     http://localhost/cgi-bin/fpingnodes.cgi?ip=10.130.1.1
-
-6/ Test reading and writing nodes.txt database with your browser:
-
-   http://localhost/cgi-bin/addnode.cgi?lat=123&lng=456&ip=10.130.1.1
-
-   $ cat /var/www/dilimesh/nodes.txt
-   123,456,10.130.1.1
-
-   http://localhost/cgi-bin/delnode.cgi?lat=123&lng=456&ip=10.130.1.1
-
-   $ cat /var/www/dilimesh/nodes.txt
-   (empty file)
-
-7/ Test signal strength daemon on each node:
-
-   $ telnet 10.130.1.1 4950
-   Trying 10.130.1.36...
-   Connected to 10.130.1.36.
-   Escape character is '^]'.
-
-   10.130.1.1 10.130.1.56 10.130.1.14
-   -64 -90 -75
-
-
-Debugging
----------
-
-1/ Monitor Apache log:
-
-  $ tail -f /var/log/apache2/access.log
-
-2/ Use Firebug on Firefox to single step, set breakpoints etc.
-
-3/ Check nodes.txt database, each line is (lat, lng, IP):
-
-  # cat /var/www/dilimesh/nodes.txt 
-
-  -34.88548650005714,138.55225324630737,10.130.1.56
-  -34.88006501016277,138.55394840240479,10.130.1.1
-  -34.87893842193011,138.55278968811035,10.130.1.23
-  -34.882511765792316,138.55210304260254,10.130.1.14
-  -34.880364257566484,138.5518455505371,10.130.1.36
-
-4/ The "dilimesh" cookie stores a lot of our state. On Firefox 3.5 you
-   can remove the dilimesh cookie using Edit-Preferences-Privacy, then
-   click on "remove individual cookies".
-
-5/ To reset to defaults:
-   
-   * move to another page (cookie is svaed when we exit page)
-   * rm -f /var/www/dilimesh/nodes.txt
-   * Delete cookie using setp (4) above
diff --git a/dilimesh/cgi-bin/addnode.cgi b/dilimesh/cgi-bin/addnode.cgi
deleted file mode 100755 (executable)
index bd78216..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-# addnode.cgi
-# David Rowe 4 Dec 2010
-#
-# CGI to add a new node
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head></head>
-<body>
-EOF
-
-lat=`echo "$QUERY_STRING" | sed -n "s/.*lat=\(.*\)&lng.*/\1/p"`
-lng=`echo "$QUERY_STRING" | sed -n "s/.*lng=\(.*\)&ip.*/\1/p"`
-ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=\(.*\)/\1/p"`
-
-echo $lat,$lng,$ip >> /var/www/dilimesh/nodes.txt
-
-echo $QUERY_STRING "<br>"
-echo "<br>"
-echo $lat $lng $ip
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/cleardb.cgi b/dilimesh/cgi-bin/cleardb.cgi
deleted file mode 100755 (executable)
index fa4433c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-# cleardb.cgi
-# David Rowe 15 Dec 2010
-#
-# CGI to delete entire node database
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head></head>
-<body>
-EOF
-
-# path to node database text file
-
-P=/var/www/dilimesh
-rm $P/nodes.txt
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/delnode.cgi b/dilimesh/cgi-bin/delnode.cgi
deleted file mode 100755 (executable)
index 5c8b115..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-# delnode.cgi
-# David Rowe 4 Dec 2010
-#
-# CGI to delete a node
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head></head>
-<body>
-EOF
-
-lat=`echo "$QUERY_STRING" | sed -n "s/lat=\(.*\)&.*/\1/pg"`
-lng=`echo "$QUERY_STRING" | sed -n "s/.*lng=\(.*\)/\1/pg"`
-
-# path to node database text file
-
-P=/var/www/dilimesh
-
-cat $P/nodes.txt | sed "/$lat,$lng.*/ d" > $P/nodes.tmp
-cp $P/nodes.tmp $P/nodes.txt
-rm $P/nodes.tmp
-
-#echo $QUERY_STRING "<br>"
-#echo "<br>"
-#echo $lat $lng
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/fpingnodes.cgi b/dilimesh/cgi-bin/fpingnodes.cgi
deleted file mode 100755 (executable)
index d0c19fa..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-# fpingnodes.cgi
-# David Rowe 5 Dec 2010
-#
-# CGI to fping a bunch of nodes
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head></head>
-<body>
-EOF
-
-ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p" | sed "s/,/ /g"`
-fping $ip -a -b1400 -r1 2>/dev/null
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/getnodes.cgi b/dilimesh/cgi-bin/getnodes.cgi
deleted file mode 100755 (executable)
index 7312089..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-# getnodes.cgi
-# David Rowe 5 Dec 2010
-#
-# CGI to return node list from database text file
-# We use a CGI rather than fetching the text file directly
-# so we can control Firefox from caching
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1">
-</head>
-<body>
-EOF
-
-NODES=/var/www/dilimesh/nodes.txt
-
-if [ -f $NODES ] ; then 
-  cat $NODES
-fi
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/getsig.cgi b/dilimesh/cgi-bin/getsig.cgi
deleted file mode 100755 (executable)
index 1850fcc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh
-# getsig.cgi
-# David Rowe 6 Dec 2010
-#
-# CGI to fetch the signal strength from a node
-# Requires the node to be running sigstr.sh script as 
-# a telnet dameon port 4950
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head></head>
-<body>
-EOF
-
-ip=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p" | sed "s/,/ /g"`
-nc $ip 4950
-echo $ip
-
-cat <<EOF
-</body>
-</html>
-EOF
diff --git a/dilimesh/cgi-bin/getvis.cgi b/dilimesh/cgi-bin/getvis.cgi
deleted file mode 100755 (executable)
index a8723b7..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-# getvis.cgi
-# David Rowe 4 Dec 2010
-#
-# CGI to fetches vis server data
-# I am sure it is possible to do this directly from Javascript
-# but I am too much of a noob.
-
-cat <<EOF
-Content-type: text/html
-
-<html>
-<head>
-<meta http-equiv="cache-control" content="no-cache">
-<meta http-equiv="pragma" content="no-cache">
-<meta http-equiv="expires" content="-1"></head>
-<body>
-EOF
-
-VIS_SERVER_HOST=`echo "$QUERY_STRING" | sed -n "s/.*ip=//p"`
-
-nc $VIS_SERVER_HOST 2005 2>/dev/null >/dev/null 
-if [ $? -eq 0 ] ; then
-  nc $VIS_SERVER_HOST 2005 | sed -n "/{/ p" 
-else
-  echo "Can't connect to Visualisation Server on $VIS_SERVER_HOST"
-fi
-
-cat <<EOF
-</body>
-</html>
-EOF
-
diff --git a/dilimesh/dilimesh/dilimesh.css b/dilimesh/dilimesh/dilimesh.css
deleted file mode 100644 (file)
index d72344f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-html,body{
-       margin:0;
-       padding:0;
-       width:100%;
-       height:100%;
-       font-family:Arial, Helvetica, sans-serif;
-}
-
-div#header{    
-       vertical-align:middle;
-       border-bottom:1px solid #000;
-}
-div#main-map{
-       width:70%;
-       height:100%;
-       float:left;
-}
-div#side{
-       width:30%;
-       float:left;
-}
-
-div#dataPanel{
-       width:90%;
-       height:50%;
-       overflow:auto;
-       border:2px solid #DDDDDD;
-}
-input{
-       width:90%;
-}
-
-input.navi{
-       font-size:12px;
-       height:30px;
-       margin-bottom:10px;
-}
-div ul{
-       margin-top:30px;
-       margin-bottom:30px;
-}
-div ul li{
-       display: inline;
-       list-style-type: none;
-       padding-right: 40px;
-       font-size:18px;
-       font-weight:bold;
-}
-
-div ul li.title{
-       font-size:22px;
-       color:#888;
-}
-
-div#header p{
-       color:#888;
-       font-size:14px;
-       padding-left:20px;
-}
-span.instruction{
-       font-weight:bold;
-       
-}
-
-.message-box { text-align: center; padding: 5px; color:#545454; width:80%;  margin:5px auto; font-size:12px;}
-.clean { background-color: #efefef; border-top: 2px solid #dedede; border-bottom: 2px solid #dedede; }
-.info  { background-color: #f7fafd; border-top: 2px solid #b5d3ff; border-bottom: 2px solid #b5d3ff; }
-.ok    { background-color: #d7f7c4; border-top: 2px solid #82cb2f; border-bottom: 2px solid #82cb2f; }
-.alert { background-color: #fef5be; border-top: 2px solid #fdd425; border-bottom: 2px solid #fdd425; }
-.error { background-color: #ffcdd1; border-top: 2px solid #e10c0c; border-bottom: 2px solid #e10c0c; }
\ No newline at end of file
diff --git a/dilimesh/dilimesh/dilimesh.html b/dilimesh/dilimesh/dilimesh.html
deleted file mode 100644 (file)
index 1c00229..0000000
+++ /dev/null
@@ -1,996 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
-<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
-<style type="text/css">
-  html { height: 100% }
-  body { height: 100%; margin: 0px; padding: 0px }
-  #map_canvas { height: 100% }
-</style>
-<title>Dili Mesh</title>
-
-<link rel="stylesheet" type="text/css" href="dilimesh.css">
-<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
-
-<script type="text/javascript">
-  /*
-     dilimesh.html
-     David Rowe 
-     Dec 4 2010
-
-     Simple mesh network mapping application used as a test bed for debugging
-     problem links in the Dili Village Telco.  
-
-     See dilimesh README.txt for more information.
-  */
-
-  var map;
-
-  // cookie params
-
-  var cookiename = "dilimesh0001";
-  var cookieexpy = 7;
-
-  // these are stored in cookie, with default values
-
-  var lat = 0;
-  var lng = 0;
-  var myzoom = 2;
-  var vis_server_ip = "192.168.1.100";
-  var update_enable = 0;
-  var update_time = 5;
-  var debug_enable  = 0;  
-  var known_location = true;
-
-  // state variables we use while dragging
-
-  var dragIp;
-  var drag_packet_loss;
-  var drag_in_progress;
-  // pathes, vis server data, node list
-
-  var pathes = []; // array of lines, used to delete them
-  var vis    = []; // array of vis server information
-  var nodes  = []; // database of nodes we keep in memory
-                   // mirrors nodes.txt but also store marker locations
-
-  // states for polling sig strength
-
-  var sigstr_node_index = 0;
-
-  // Called when we load page
-
-  function initialize() {
-
-    // we use our cookie as a mini-databse for map location, 
-    // control panel values etc
-    getCookie();
-
-    var myLatlng = new google.maps.LatLng(lat, lng);
-    var myOptions = {
-      zoom: myzoom,
-      center: myLatlng,
-      scaleControl: true,
-      mapTypeId: google.maps.MapTypeId.ROADMAP
-    }
-    map = new google.maps.Map(document.getElementById("main-map"), myOptions);
-
-    // we don't want manual placement of nodes, use vis server to pop
-    // them up
-    //google.maps.event.addListener(map, 'click', function(event) {
-    //  placeMarker(event.latLng);
-    //});
-
-    // set up initial form values
-
-    document.control_panel.vis_server_ip.value = vis_server_ip;
-    document.control_panel.update_time.value = update_time;
-    document.control_panel.update_enable.checked = update_enable;
-    document.control_panel.debug_enable.checked = debug_enable;
-    var html = '<a href="/cgi-bin/getvis.cgi?ip=' + vis_server_ip + ' ">Test Vis Server Connection</a>';
-    document.getElementById('test_vis_server').innerHTML = html;
-
-    // read from nodes.txt database text file on server and init map
-    
-    downloadUrl("/cgi-bin/getnodes.cgi", processMarkers);
-  }
-
-
-  // Slurp up nodes.txt when web pages loads
-
-  processMarkers = function(doc, status) {
-    log("processMarkers");
-
-    // split the document into lines
-
-    var lines = doc.split("\n");
-    for (var i=0; i<lines.length; i++) {
-      if (lines[i].length > 1) {
-
-        // split each line into parts separated by "," and use the contents
-
-        parts = lines[i].split(",");
-        if (parts.length > 1) {
-          var lat = parseFloat(parts[0]);
-          var lng = parseFloat(parts[1]);
-          var ip = parts[2];
-          if (ip == undefined) {
-            ip = "";
-          }
-
-          // sanity check, make sure no duplicate IPs
-   
-          if (dupIp(ip))
-            log("Error - Duplicate IP " + ip + " in nodes.txt");
-          else
-            addNewNode(lat, lng, ip, false);
-        }
-      }
-    }
-
-    // initial map display, only if we have a sensible map location.  Otherwise
-    // new nodes will be placed in middle of current default location
-    if (known_location)
-      poll();       
-
-    // kick off timer process that periodically fires off vis and fping CGIs
-
-    timer();
-  }
-
-
-  // check for duplicate IPs
-
-  function dupIp(ip) {
-
-    if ( (ip == undefined) || (ip == ""))
-      return false;
-
-    // walk nodes list looking for this IP
-
-    for (var j=0; j<nodes.length; j++) {
-        if (nodes[j].ip == ip) {
-          return true;
-        }
-      }
-
-    return false;
-
-  }
-
-
-  // Process the Vis server information 
-
-  processVis = function(doc, status) {
-    log("processVis");
-
-    if (drag_in_progress)
-      return;
-
-    // extract the JSON lines from doc returned by getvis.cgi
-    // there is surely a better way to do this but I am a JSON noob
-
-    var lines = doc.split("\n");
-    var vis_str = "vis = {data: [\n";
-    for (var i=0; i<lines.length; i++) {
-      if (lines[i].length > 1) {
-        if (lines[i].indexOf('{') != -1) {
-          vis_str = vis_str + lines[i] + "\n";
-        }
-      }
-    }
-    
-    vis_str = vis_str + "]\n};"
-    eval(vis_str); // run time compilation of JSON string
-    
-    // OK now we have an array that we can parse for new nodes
-
-    // walk vis list by router
-
-    var new_nodes = 0;
-    for (var i=0; i<vis.data.length; i++) {
-
-      // see if this node exists in our database
-      var node_exists = 0;
-      for (var j=0; j<nodes.length; j++) {
-        if (vis.data[i].router == nodes[j].ip) {
-          node_exists = 1;
-        }
-      }    
-
-      // create node if it doesn't exists already
-
-      if (node_exists == 0) {
-         // small offset makes sure we don't create them all on one spot
-         var location = new google.maps.LatLng(lat + 1E-4*nodes.length, lng);
-         placeMarker(location, vis.data[i].router, true);
-      }
-    }
-
-    // walk vis list by neighbour
-
-    for (var i=0; i<vis.data.length; i++) {
-
-      if (vis.data[i].neighbour != undefined) {
-
-        // see if this node exists in our database
-        var node_exists = 0;
-        for (var j=0; j<nodes.length; j++) {
-          if (vis.data[i].neighbour == nodes[j].ip) {
-            node_exists = 1;
-          }
-        }    
-
-        // create node if it doesn't exists already
-
-        if (node_exists == 0) {
-          // small offset makes sure we don't create them all on one spot
-          var location = new google.maps.LatLng(lat + 1E-4*nodes.length, lng);
-          placeMarker(location, vis.data[i].neighbour, true);
-        }
-      }
-    }
-
-    // now all nodes are logged in text file and nodes database
-    // lets see if we any have routes between them
-
-    drawPathesBetweenNodes();
-  }
-
-  function poll() {
-
-    // fire off vis server CGI
-
-    downloadUrl("/cgi-bin/getvis.cgi?ip=" + vis_server_ip, processVis);
-    // fire off fping CGI
-
-    var ips = "ip=";
-    for (var j=0; j<nodes.length; j++) {
-      if (nodes[j].ip != "") {
-        ips = ips + nodes[j].ip;
-        if (j != (nodes.length-1)) {
-          ips = ips + ",";
-        }
-      }
-    }    
-                                                 
-    if (ips != "") {
-      downloadUrl("/cgi-bin/fpingnodes.cgi?" + ips, processFping);
-
-      // set up HTML for manual ping test
-    
-      var html = '<a href="/cgi-bin/fpingnodes.cgi?' + ips + ' ">Ping nodes</a>';
-      document.getElementById('ping_nodes').innerHTML = html;
-    }
-
-    // fire off next sig strength CGI, we iterate these over time to keep
-    // network load nominal
-
-    if (nodes[sigstr_node_index] != undefined) {
-      downloadUrl("/cgi-bin/getsig.cgi?ip=" + nodes[sigstr_node_index].ip, processgetSig);
-      document.getElementById('sigstr_current_node').innerHTML = nodes[sigstr_node_index].ip;
-    }
-    sigstr_node_index++;
-    if (sigstr_node_index >= nodes.length)
-      sigstr_node_index = 0;
-  }
-
-
-  // this function calls itself every update_time seconds
-  // used for peridoic updates (polling) of network stats
-
-  function timer() {
-    var today=new Date();
-    var h=today.getHours();
-    var m=today.getMinutes();
-    var s=today.getSeconds();
-
-    // set time, add a zero in front of numbers < 10
-
-    m=checkTime(m);
-    s=checkTime(s);
-    document.getElementById('time').innerHTML=h+":"+m+":"+s;
-
-    if (update_enable)
-      poll();
-
-    // restart this timer after update_time seconds
-   
-    t=setTimeout('timer()',update_time*1000);
-  }
-
-
-  function checkTime(i) {
-    if (i<10) {
-      i="0" + i;
-    }
-    return i;
-  }
-
-
-  // called when Fping CGI returns
-
-  function processFping(doc, status) {
-
-    //log("processFping");
-
-    if (drag_in_progress)
-      return;
-
-    // walk node list and set colour depending on ping stats
-
-    var nodes_reachable = 0;
-    var nodes_poor_packet_loss = 0;
-    for (var j=0; j<nodes.length; j++) {
-      if (doc.indexOf(nodes[j].ip) == -1) {
-        // no ping from node
-        nodes[j].marker.setIcon("node_dead.png");
-        // update IIR averaging filter
-        nodes[j].packet_loss = 0.875*nodes[j].packet_loss + 0.125;
-      }
-      else {
-
-        // update IIR averaging filter
-
-        nodes[j].packet_loss = 0.875*nodes[j].packet_loss;
-        nodes_reachable++;
-      }
-
-      // Change icon based on packet loss
-
-      if (nodes[j].packet_loss < 0.1) {
-           nodes[j].marker.setIcon("node_good.png");
-      }
-      if ((nodes[j].packet_loss > 0.1) && (nodes[j].packet_loss < 0.9)) {
-        nodes[j].marker.setIcon("node_packet_loss.png");
-        nodes_poor_packet_loss++;
-      }
-      if (nodes[j].packet_loss > 0.9) {
-        nodes[j].marker.setIcon("node_dead.png");
-        nodes_poor_packet_loss++;
-      }
-                                                 
-      //log("  nodes[j].packet_loss");
-
-      var packet_loss_formatted = Math.round(nodes[j].packet_loss*100);
-
-      nodes[j].marker.setTitle(nodes[j].ip + ' Packet Loss: ' + packet_loss_formatted + '%');  
-      var html  = '<table>';
-          html += '<tr><th>' + nodes[j].ip + '</th></tr>';
-          html += '<tr><td>Packet Loss</td><td>' + packet_loss_formatted + '%</td></tr>';
-      if (nodes[j].neighbour_ips != undefined) {
-        for(var i=0; i<nodes[j].neighbour_ips.length; i++) {
-          html += '<tr><td>' + trim(nodes[j].neighbour_ips[i]) + '</td><td>';
-          html += trim(nodes[j].neighbour_sigs[i]) + ' dBm</td><td>';
-       }
-      }
-      html += '</table>';
-
-      nodes[j].infowindow.setContent(html);  
-    }  
-
-    document.getElementById('nodes_total').innerHTML = nodes.length;
-    document.getElementById('nodes_reachable').innerHTML = nodes_reachable;  
-    document.getElementById('nodes_poor_packet_loss').innerHTML = nodes_poor_packet_loss;  
-  }
-
-
-  // remove leading and trailing whitespace from a string
-
-  function trim(stringToTrim) {
-       return stringToTrim.replace(/^\s+|\s+$/g,"");
-  }
-
-
-  // called when getsig.cgi returns to grok signal
-  // strength information
-
-  function processgetSig(doc, status) {
-    log("processgetSig");
-   
-    // extract our lines from the HTML using state machine
-   
-    var lines = doc.split("\n");
-    var ip;
-    var neighour_ips;
-    var neighour_sigs
-    var state = "start";
-    var next_state;
-    for (var j=0; j<lines.length; j++) {
-
-      next_state = state;
-      if (state == "start") {
-        if (lines[j].indexOf('sigstr') != -1)
-          next_state = "read ips";
-      }
-      if (state == "read ips") {
-        neighbour_ips = lines[j].split(" ");
-        next_state = "read sigs";
-      }
-      if (state == "read sigs") {
-        neighbour_sigs = trim(lines[j]).split(" ");
-        next_state = "read ip";
-      }
-      if (state == "read ip") {
-        ip =lines[j];
-        next_state = "finished";
-      }
-      state = next_state;
-    }
-
-    if (state == "finished") {
-     // walk nodes list to match ip
-
-      for (var j=0; j<nodes.length; j++) {
-        if (nodes[j].ip == ip) {
-          nodes[j].neighbour_ips  = neighbour_ips;
-          nodes[j].neighbour_sigs = neighbour_sigs;
-          var html="<table>";
-          for(var i=0; i<neighbour_ips.length; i++) {
-            html += '<tr><td>' + trim(neighbour_ips[i]) + '</td><td>' + trim(neighbour_sigs[i]) + ' dBm</td></tr>';
-          }
-          html += '</table>';
-         document.getElementById('sigstr_last_node').innerHTML = ip;
-         document.getElementById('sigstr_results').innerHTML = html;
-        }    
-      }
-    }
-  }
-
-
-  // calculate distance between two points
-
-  rad = function(x) {return x*Math.PI/180;}
-
-  distHaversine = function(p1, p2) {
-    var R = 6371; // earth's mean radius in km
-    var dLat  = rad(p2.lat() - p1.lat());
-    var dLong = rad(p2.lng() - p1.lng());
-
-    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
-            Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
-    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
-    var d = R * c;
-
-    return d.toFixed(3);
-  }
-
-
-  // draw lines indicating links between nodes 
-
-  function drawPathesBetweenNodes() {
-
-    // delete all existing paths, this is inefficient but is OK for a first pass
-      
-    if (pathes) {
-      for (j in pathes) {
-        pathes[j].setMap(null);
-      }
-      pathes.length = 0;
-    }
-
-    // walk vis array looking for routes, I think this actually draws
-    // routes twice
-
-    for (var i=0; i<vis.data.length; i++) {
-   
-      if (vis.data[i].neighbour != undefined) {
-        // this entry in vis array has a route and a neighbour
-
-        router_ip = vis.data[i].router;
-        neighbour_ip = vis.data[i].neighbour;
-
-        // walk nodes list to find router location on map
-
-        var router_location;
-        for (var j=0; j<nodes.length; j++) {
-          if (router_ip == nodes[j].ip) {
-            router_location = nodes[j].marker.position;
-          }
-        }    
-
-        // walk nodes list to find neighbour location on map
-
-        var neighbour_location;
-        for (var j=0; j<nodes.length; j++) {
-          if (neighbour_ip == nodes[j].ip) {
-            neighbour_location = nodes[j].marker.position;
-          }
-        }    
-
-       if ((router_location != undefined) && (neighbour_location != undefined)) {
-         // draw polyline between locations
-
-          var coords = [
-            router_location,
-            neighbour_location
-          ];
-          var path = new google.maps.Polyline({
-            path: coords,
-            strokeColor: "#008000",
-            strokeOpacity: 0.5,
-            strokeWeight: 5
-          });
-          path.setMap(map);
-
-          // click on line to get distance and path loss estimates
-
-          google.maps.event.addListener(path, "click", function() {
-            var path = this.getPath();
-            var dist = distHaversine(path.b[0], path.b[1]) * 1000;
-
-            // est rx power: 
-            //   MP tx pwr between 15 and 20dB depending on rate, so use 17dB
-            //   roughly 2dB tx and rx antennas
-            //   100dB loss for 1000m, 6dB more for double distance
-
-            var path_loss = 100.0 + 20*Math.log(dist/1000)/Math.log(10);
-            path_loss =  Math.round(path_loss);
-            var est_rx_sig = 17 + 2 + 2 - path_loss;
-
-            document.getElementById('distance').innerHTML = dist + ' m';
-            document.getElementById('path_loss').innerHTML = -path_loss + ' dBm';
-            document.getElementById('est_rx_sig').innerHTML = est_rx_sig + ' dBm';
-          });
-         
-          pathes.push(path);
-        }  
-      }          
-    }
-  }
-
-
-  // sets up map for a new Node
-  // adds node to nodes[] array but doesn't write to text file
-
-  function addNewNode(lat, lng, newIp, isNewNode) {
-
-    // create the marker
-
-    var location = new google.maps.LatLng(lat, lng);
-    var newMarker = new google.maps.Marker(
-      {position: location, 
-       map: map, 
-       draggable: true,
-       title: newIp,
-       icon: "node_good.png" });
-
-    if (isNewNode) {
-      newMarker.setAnimation(google.maps.Animation.BOUNCE);
-    }
-
-    // add to nodes array
-
-    var newInfoWindow = new google.maps.InfoWindow(
-      { content: newIp
-      });
-    var newNode = {marker : newMarker, 
-                   ip: newIp, 
-                   infowindow: newInfoWindow, 
-                   packet_loss: 0.0};
-    nodes.push(newNode); 
-
-    // add listeners
-
-    google.maps.event.addListener(newMarker, "dragstart", function() {
-
-      drag_in_progress = 1;
-
-      // remove node from nodes array
-
-      var new_nodes = [];
-      for (var j=0; j<nodes.length; j++) {
-        if (nodes[j].marker.position != newMarker.position) {
-          new_nodes.push(nodes[j]);
-        }
-        else {
-          // preserve some states for when we drop it
-          dragIp = nodes[j].ip;
-          drag_packet_loss = nodes[j].packet_loss;
-        }
-      }
-      nodes = new_nodes;
-
-      // delete node from text file
-
-      var url;
-      url = "/cgi-bin/delnode.cgi?" + "lat=" + this.position.lat() + "&" + "lng=" +
-             this.position.lng();
-      downloadUrl(url, function(doc) { });
-    });
-
-    google.maps.event.addListener(newMarker, "dragend", function() {
-
-      // stop any bouncing
-      newMarker.setAnimation(null);
-
-      // add node to nodes array
-
-      var newInfoWindow = new google.maps.InfoWindow(
-        {  content: dragIp
-        });
-      var newNode = {marker : newMarker, 
-                     ip: dragIp, 
-                     infowindow: newInfoWindow, 
-                     packet_loss: drag_packet_loss
-      };
-      nodes.push(newNode); 
-     
-      // add node to text file
-
-      var url;
-      url = "/cgi-bin/addnode.cgi?" + "lat=" +  this.position.lat() + "&" + "lng=" +
-            this.position.lng() + "&" + "ip=" + dragIp;
-      downloadUrl(url, function(doc) { });
-
-      drawPathesBetweenNodes();
-
-      drag_in_progress = 0;
-    });
-
-    google.maps.event.addListener(newMarker, "click", function() {
-
-      // walk node list to find our InfoWindow
-
-      for (var j=0; j<nodes.length; j++) {
-        if (nodes[j].marker.position == newMarker.position) {
-          nodes[j].infowindow.open(map, newMarker);
-        }
-      }    
-
-    });
-
-    google.maps.event.addListener(newMarker, "rightclick", function() {
-
-      // remove node from nodes array
-
-      var new_nodes = [];
-      for (var j=0; j<nodes.length; j++) {
-        if (nodes[j].marker.position != newMarker.position) {
-          new_nodes.push(nodes[j]);
-        }
-      }
-      nodes = new_nodes;
-
-      // delete node from text file
-
-      var url;
-      url = "/cgi-bin/delnode.cgi?" + "lat=" +  this.position.lat() + "&" + "lng=" +  this.position.lng();
-      downloadUrl(url, function(doc) { });
-      this.setMap(null);
-
-      drawPathesBetweenNodes();
-
-    });
-
-  }
-
-
-  // save state (config info) to our cookie
-
-  function setCookie() {
-    var cookietext = cookiename;
-    cookietext += "=" + map.getCenter().lat();
-    cookietext += "|" + map.getCenter().lng() + "|" + map.getZoom();
-    cookietext += "|" + vis_server_ip + "|" + update_time;
-    cookietext += "|" + update_enable + "|" + debug_enable;
-    if (cookieexpy) {
-      var exdate=new Date();
-      exdate.setDate(exdate.getDate()+cookieexpy);
-      cookietext += ";expires="+exdate.toGMTString();
-    }
-    
-    // write the cookie
-
-    document.cookie = cookietext;
-  }
-
-
-  // Grab a bunch of config info from our cookie
-
-  function getCookie() {
-                       
-    if (document.cookie.length > 0) {
-      cookieStart = document.cookie.indexOf(cookiename + "=");
-
-      // lets see if our cookie exists
-
-      if (cookieStart!=-1) {
-        cookieStart += cookiename.length+1; 
-        cookieEnd=document.cookie.indexOf(";",cookieStart);
-        if (cookieEnd==-1) {
-          cookieEnd=document.cookie.length;
-        }
-        cookietext = document.cookie.substring(cookieStart,cookieEnd);
-        // split the cookie text and create the variables
-
-        bits = cookietext.split("|");
-        lat = parseFloat(bits[0]);
-        lng = parseFloat(bits[1]);
-        myzoom = parseInt(bits[2]);
-        vis_server_ip = (bits[3]);
-        update_time = parseInt(bits[4]);
-        update_enable = parseInt(bits[5]);
-        debug_enable = parseInt(bits[6]);
-      }
-    } 
-    else {
-      known_location = false; // don't detect and display new nodes
-      alert("Move to your " +
-            "current location then refresh to detect nodes.");              
-
-    }
-
-  }
-
-
-  // clear database and set cookie to defaults
-
-  function clearDatabase() {
-
-    // call CGI to rm nodes.txt
-
-    downloadUrl("/cgi-bin/cleardb.cgi", function(doc) { });
-    nodes = [];    
-
-    // I would really like to clear cookie but can't work out how, so
-    // set to defaults instead, 
-
-    var myLatLng = new google.maps.LatLng(0, 0);
-    map.setCenter(myLatLng);
-    map.setZoom(2);
-    update_enable = 0;                          
- }
-
-
-  // called when we click to add a node on map
-
-  function placeMarker(location, ip, isNewNode) {
-    if (ip == undefined) {
-      ip = "";
-    }
-    if (isNewNode == undefined) {
-      isNewNode = false;
-    }
-
-    addNewNode(location.lat(), location.lng(), ip, isNewNode);
-
-    // save to marker file by calling a CGI
-
-    var url;
-    url = "/cgi-bin/addnode.cgi?" + "lat=" + location.lat() + "&" + "lng=" + location.lng() + "&" + "ip=" + ip;
-    downloadUrl(url, function(doc) { });
-  }
-  
-  /**
-  * Returns an XMLHttp instance to use for asynchronous
-  * downloading. This method will never throw an exception, but will
-  * return NULL if the browser does not support XmlHttp for any reason.
-  * @return {XMLHttpRequest|Null}
-  */
-  function createXmlHttpRequest() {
-    try {
-      if (typeof ActiveXObject != 'undefined') {
-        return new ActiveXObject('Microsoft.XMLHTTP');
-      } else if (window["XMLHttpRequest"]) {
-        return new XMLHttpRequest();
-      }
-     } catch (e) {
-     changeStatus(e);
-     }
-   return null;
-  };
-
-  /**
-  * This functions wraps XMLHttpRequest open/send function.
-  * It lets you specify a URL and will call the callback if
-  * it gets a status code of 200.
-  * @param {String} url The URL to retrieve
-  * @param {Function} callback The function to call once retrieved.
-  */
-  function downloadUrl(url, callback) {
-    var status = -1;
-    var request = createXmlHttpRequest();
-    if (!request) {
-      return false;
-    }
-
-    request.onreadystatechange = function() {
-      if (request.readyState == 4) {
-        try {
-          status = request.status;
-        } catch (e) {
-          // Usually indicates request timed out in FF.
-        }
-        if (status == 200) {
-          callback(request.responseText, request.status);
-          request.onreadystatechange = function() {};
-        }
-      }
-    }
-    request.open('GET', url, true);
-    try {
-      request.send(null);
-    } catch (e) {
-      changeStatus(e);
-    }
-  };
-
-  function log(message) {
-    if (debug_enable == 1) {
-      message_list = document.getElementById("debugging_messages");
-      log_message = document.createTextNode(message);
-      log_list_item = document.createElement('li');
-      log_list_item.appendChild(log_message);
-      message_list.appendChild(log_list_item);
-    }
-  }
-
-  function debugClicked() {
-    if (document.control_panel.debug_enable.checked)
-      debug_enable = 1;
-    else
-      debug_enable = 0;
-  }
-
-  function updateEnableClicked() {
-    if (document.control_panel.update_enable.checked)
-      update_enable = 1;
-    else
-      update_enable = 0;
-  }
-
-  function setVisServerIp() {
-    vis_server_ip = document.control_panel.vis_server_ip.value;
-    var html = '<a href="/cgi-bin/getvis.cgi?ip=' + vis_server_ip + ' ">Test Vis Server Connection</a>';
-    document.getElementById('test_vis_server').innerHTML = html;
-  }
-
-  function setUpdateTime() {
-    update_time = document.control_panel.update_time.value;
-  }
-
-</script>
-
-</head>
-<body onload="initialize()" onunload="setCookie()">
-
-  <div id="main-map">
-  </div>
-
-  <div id="side">
-
-    <h3>Help</h3>
-      <table>
-        <tr><td width="5%"></td><td><a href="https://freetel.svn.sourceforge.net/svnroot/freetel/dilimesh/README.txt">DiliMesh README</a></td></tr>
-      </table>
-
-    <div id="stats" style="width: 100%;">
-      <h3>Network Stats</h3>
-        <table>
-         <tr><td width="5%"></td><td>Time</td><td><div id="time"></div></td></tr>
-         <tr><td></td><td>Nodes Reachable</td><td><div id="nodes_reachable"></div></td></tr>
-         <tr><td></td><td>Nodes Poor Packet Loss</td><td><div id="nodes_poor_packet_loss"></div></td></tr>
-         <tr><td></td><td>Nodes Total</td><td><div id="nodes_total"></div></td></tr>
-        </table>
-    </div>
-
-    <div id="control" style="width: 100%;">
-      <h3>Contol Panel</h3>
-      <form name="control_panel">
-        <table>
-       <tr>
-          <td width="5%">
-          <td>Visualisation Server IP</td>
-          <td colspan="2"><input type="text" name="vis_server_ip" size="15"></td>
-          <td width="50"><input type="submit" value="Set" onclick="setVisServerIp()"></td>
-        </tr>
-        <tr>
-          <td></td>
-         <td>Update Enable</td>
-          <td><input type="checkbox" name="update_enable" value="1" onclick="updateEnableClicked()"></td>
-        </tr>
-        <tr>
-          <td></td>
-         <td>Update Time (s)</td>
-          <td><input type="text" name="update_time" size="3"></td>
-          <td width="30%"></td>
-          <td width="50"><input type="submit" value="Set" onclick="setUpdateTime()"></td>
-        </tr>
-        <tr>
-          <td></td>
-         <td>Clear Database</td>
-          <td></td>
-          <td width="30%"></td>
-          <td width="60"><input type="submit" value="Clear" onclick="clearDatabase()"></td>
-        </tr>
-        <tr>
-         <td></td>
-          <td>Debug Messages</td>
-          <td><input type="checkbox" name="debug_enable" onclick="debugClicked()"></td>
-        </tr>
-        </table>
-      </form>
-
-      <h3>Signal Strength</h3>
-        <table>
-        <tr>
-         <td width="5%"></td>
-          <td>Currently Polling</td>
-          <td><div id="sigstr_current_node"></div></td>
-        </tr>
-        <tr>
-         <td></td>
-          <td>Last Node that<br>Responded</td>
-          <td><div id="sigstr_last_node"></div></td>
-        </tr>
-        <tr>
-         <td></td>
-          <td valign=top>Results</td>
-          <td><div id="sigstr_results"></div></td>
-        </tr>
-        </table>
-
-      <h3>Distance</h3>
-        <table>
-        <tr>
-         <td width="5%"></td>
-          <td valign=top>Distance</td>
-          <td><div id="distance"></div></td>
-        </tr>
-        <tr>
-         <td></td>
-          <td valign=top>Path Loss</td>
-          <td><div id="path_loss"></div></td>
-        </tr>
-        <tr>
-         <td></td>
-          <td valign=top>Est Rx Signal</td>
-          <td><div id="est_rx_sig"></div></td>
-        </tr>
-        </table>
-    </div>
-
-    <div id="tests" style="width: 100%;">
-      <h3>Tests</h3>
-      <ol>
-       <li><a href="/cgi-bin/getnodes.cgi">Test nodes.txt database</a><br>
-        <li><div id="test_vis_server">&nbsp</div>
-        <li><div id="ping_nodes">&nbsp</div>
-      </ol>
-    </div>
-
-    <div id="debugging_output" style="width: 100%;">
-      <h3>Debugging Output</h3>
-      <ol id="debugging_messages">
-      </ol>
-    </div>
-  </div>
-
-
-</body>
-</html>
diff --git a/dilimesh/dilimesh/node_dead.png b/dilimesh/dilimesh/node_dead.png
deleted file mode 100644 (file)
index 88be550..0000000
Binary files a/dilimesh/dilimesh/node_dead.png and /dev/null differ
diff --git a/dilimesh/dilimesh/node_good.png b/dilimesh/dilimesh/node_good.png
deleted file mode 100644 (file)
index 056f1c9..0000000
Binary files a/dilimesh/dilimesh/node_good.png and /dev/null differ
diff --git a/dilimesh/dilimesh/node_packet_loss.png b/dilimesh/dilimesh/node_packet_loss.png
deleted file mode 100644 (file)
index 5842080..0000000
Binary files a/dilimesh/dilimesh/node_packet_loss.png and /dev/null differ
diff --git a/dilimesh/dilimesh_screenshot.png b/dilimesh/dilimesh_screenshot.png
deleted file mode 100644 (file)
index 7c26086..0000000
Binary files a/dilimesh/dilimesh_screenshot.png and /dev/null differ
diff --git a/dilimesh/scripts/S99sigstr b/dilimesh/scripts/S99sigstr
deleted file mode 100755 (executable)
index a33f816..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-telnetd -l /usr/sbin/sigstr.sh -p 4950
diff --git a/dilimesh/scripts/sigstr.sh b/dilimesh/scripts/sigstr.sh
deleted file mode 100755 (executable)
index 726458a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh
-# node_tune.sh
-# David Rowe 13 April 2010
-#
-# Prints information useful for tuning a mesh node
-#
-# Useful to run as a telnet login, e.g.
-#   telnetd -l /usr/sbin/node_tune.sh -p 4950
-# will let you plug a laptop into eth0 and "telnet 192.168.1.20 4950"
-# to run this script
-
-  # list of nodes this node can see in IP and MAC order
-  
-  IP=`cat /proc/net/arp | grep "10.130.1" | awk '{ print $1 }'`
-  MAC=`cat /proc/net/arp | grep "10.130.1" | awk '{ print $4 }'`
-  
-  echo
-  echo "sigstr"
-  echo $IP
-  for m in $MAC
-  do
-    wlanconfig ath0 list | grep $m | awk '{ printf " %s",$6 }'
-  done
-  echo
-
-
-
-