$value) { //WXC 6-30-2017: removed links for services that have no link if ($value == NULL) { $serviceList .= '
'. $key; }else { //WXC 6-30-2017: Moved
from after link to before the link, //made the pop up look better. $serviceList .= "
" . $key . ""; } } } return $serviceList; } /** * loadLinkList * This function iterates through the topology array to build a leaflet package polyline * There are four types of links defined, each is represented by a different color. * RF Link - Standard Mesh Node link * DTD Link - Mesh nodes connected by direct link ( typically via a switch ) * Tunnel Link - * Infinite Link - Links reported by and marked as unusable by olsr * * @param $NodeList * @param $TopoList * * @return mixed */ function load_LinkList($NodeList, $TopoList) { global $MESH_SETTINGS; $linkList = ""; if (isset($TopoList)) { foreach ($TopoList as $value) { if ($value['nodelat'] && $value['linklon']) //if there's no location info ignore the entry { $node_lat = $value['nodelat']; $node_lon = $value['nodelon']; $link_lat = $value['linklat']; $link_lon = $value['linklon']; $display_color = "red"; $display_weight = 2; $display_opacity = 1; $display_offset = 2; $map_LayerAssigned = ""; $tunnel = 0; $dtd = 0; $moreThanTen = 0; $infinite = 0; $nodeHasTunnel = 0; $linkHasTunnel = 0; $nodeName = $value['node']; $linkName = $value['linkto']; if ($value['cost'] == 1.0 && !($tunnel)) //find the tunnels { foreach ($NodeList as $searching_for_tunnels) { if ($searching_for_tunnels['node'] == $nodeName) { if ($searching_for_tunnels['active_tunnel_count'] >= 1) { $nodeHasTunnel = 1; } } if ($searching_for_tunnels['node'] == $linkName) { if ($searching_for_tunnels['active_tunnel_count'] >= 1) { $linkHasTunnel = 1; } } if (($linkHasTunnel) && ($nodeHasTunnel)) { $tunnel = 1; $nodeHasTunnel = 0; $linkHasTunnel = 0; $display_color = $MESH_SETTINGS['Link_Tunnel']; $dtd = 1; $display_opacity = 0.5; $map_LayerAssigned = "tunnelLinks"; } } } if ($value['cost'] == 0.1 && $value['distance'] <= 0.7) //find DTD links (always a cost of 0.1) { $display_color = $MESH_SETTINGS['DTD_Link_Minus']; $dtd = 1; $display_opacity = 0.2; $map_LayerAssigned = 'dtdLinks'; } //this is for the "other" DTD links //using other wireless tech to create links that are seen as "DTD" by the AREDN software if ($value['cost'] == 0.1 && $value['distance'] > 0.7) { $display_color = $MESH_SETTINGS['DTD_Link_Plus']; $dtd = 1; $display_opacity = 0.4; $map_LayerAssigned = 'dtdLinks'; } //find the "infinite cost" links (they show as "INFINITE" in the olsr files the other script changes that to 99.99) if ($value['cost'] == 99.99) { $display_color = $MESH_SETTINGS['Link_Infinite']; $infinite = 1; $display_opacity = 0.2; $map_LayerAssigned = 'infiniteLinks'; } //links with a cost of less than 1.0 but NOT tunnels or DTD links //tunnels are always 1.0 and DTD is always 0.1 if (($value['cost'] <= 1.000) && ($value['cost'] != 0.1) && !($tunnel)) { //these will always be a solid green $display_color = $MESH_SETTINGS['Link_GOOD']; $display_opacity = 0.5; $map_LayerAssigned = 'rfLinks'; } //links of greater than 10.000 ETX, but not "INFINITE" (these links are always red) if ($value['cost'] > 10.000 && $value['cost'] != 99.99) { $display_color = $MESH_SETTINGS['Link_BAD']; $moreThanTen = 1; $display_opacity = 0.3; $map_LayerAssigned = 'rfLinks'; } //now for the more normal links //less than ETX 5.0 links if ($value['cost'] < 5 && !($dtd) && !($tunnel)) { $display_color = sprintf("#%02XFF00", ($value['cost'] - 1) * (255 / (5 - 1))); $map_LayerAssigned = 'rfLinks'; } //more than ETX 5.0 links if ($value['cost'] > 5 && !($moreThanTen) && !($infinite)) { $display_color = sprintf("#FF%02X00", ($value['cost'] - 1) * (255 / (5 - 1)) - 255); $display_opacity = 0.5; $map_LayerAssigned = 'rfLinks'; } if ($map_LayerAssigned) { $linkList .= "L.polyline([[" . $node_lat . "," . $node_lon . "],[" . $link_lat . "," . $link_lon . "]], {color: '" . $display_color . "', opacity: " . $display_opacity . ", weight: " . $display_weight . ", offset: " . $display_offset . "}) .bindPopup(\" $nodeName to $linkName
Cost: " . $value['cost'] . "\") .addTo(" . $map_LayerAssigned . "),\n"; } } } } return $linkList; } /** * loadLinkedTO * This routine create a HTML formatted text list of link details. * The information gathered here is display as part of the node popup detail. * * @param $node_info * @param $TopoList * * @return string */ function load_LinkedTO($node_info, $TopoList) { $linkedToList = ""; $linkInfoForStationPopups = array($node_info['node'] => array()); //don't init what is going to be an array as a string!! //$linkInfoForStationPopups = array($node_info['node'] => ""); $node = $node_info['node']; //and build a big 3D array of it all //like this: //array // "NodeName" // "1stLinkedNodesName" // "CostFrom" // "CostTo" // "distance" // "bearing" // "2ndLinkedNodesName" // "CostFrom" // "CostTo" //etc..etc.. if (isset($TopoList)) { foreach ($TopoList as $value) { //if there's no location info (at each end of the link) ignore the entry if ($value['nodelat'] && $value['linklon']) { //this is the section that is exploding in php7.2.3 if ($value['linkto'] == $node) { //this will be the cost FROM each linked station back TO the node we are currently looking at in the while loop //original line (leave for now) //$linkInfoForStationPopups[$node_info['node']][$value['node']]["costFrom"] = $value['cost']; //the new line //had to create the array correctly! fixed 3-28-2018 - wxc $linkInfoForStationPopups[$node_info['node']][$value['node']] = array('costFrom' => $value['cost'], 'costTo' => "", 'distance' => "", 'bearing' => ""); } if ($value['node'] == $node) { //$linkedNodesKeyNameArray = array("costTo", "distance", "bearing"); //this will be the cost TO each linked station FROM the node we are currently looking at in the while loop //distance and bearing added too for goo measure! :) //$linkInfoForStationPopups[$node_info['node']][$value['linkto']] = array_fill_keys($linkedNodesKeyNameArray, ""); $linkInfoForStationPopups[$node_info['node']][$value['linkto']]["costTo"] = $value['cost']; //add in the distance to that linked node $linkInfoForStationPopups[$node_info['node']][$value['linkto']]["distance"] = $value['distance']; //add in the bearing to that linked node $linkInfoForStationPopups[$node_info['node']][$value['linkto']]["bearing"] = $value['bearing']; } } } } //now take all that info back out and put into a properly formatted string variable that we'll use later] foreach ($linkInfoForStationPopups as $nodeNameLinkArray => $linktoArray) { if ($linktoArray > "") { foreach ($linktoArray as $linkedNodeName => $costArray) { if (($costArray['costTo'] == 0.1) && ($costArray['costFrom'] == 0.1)) { $display_cost = ' (DTD) '; } else { $display_cost = " (" . $costArray['costTo'] . "/" . $costArray['costFrom'] . ") "; } $linkedToList .= $linkedNodeName . $display_cost . $costArray['distance'] . " mi " . $costArray['bearing'] . "°
"; } } } return $linkedToList; } /** * buildMarker * This routine builds Mesh Markers. * These mesh markers are added to various map layer depending upon the type of node * The currently defined Mesh Markers are categorized by frequency * 2Ghz, 3Ghz, 5Ghz, 900Mhz, Linux systems * * Mesh Markers are stored in the node_info table, which is updated by the get-map-info.php routine * * @param $node_info * @param $node_ServiceList * @param $node_LinkedList * @param $node_FirmwareStatus * * @return string AssignedLayer */ function build_Marker($node_info, $node_ServiceList, $node_LinkedList, $node_FirmwareStatus) { $markerList = ""; $nodeUrl = "" . $node_info['node'] . ""; //Now we look at the 'channel' value, for each node, from the node_info database. //Then compare it to what we know about each bands channels //if we find a match, we assume we're in that band... if ($node_info['firmware_version'] == "Linux") { // Linux Devices ( Special for SNOOPY ) $icon = "linuxCircle"; $band = "Linux"; $AssignedLayer = 'otherStations'; } else { switch ((wxc_checkBand($node_info['channel']))) { case "2GHz": // 2.4GHz devices $icon = "twoRadioCircle"; $band = "2.4GHz"; $AssignedLayer = 'twoGHzStations'; break; case "3GHz": // 3GHz devices $icon = "threeRadioCircle"; $band = "3.4GHz"; $AssignedLayer = 'threeGHzStations'; break; case "5GHz": // 5GHz devices $icon = "fiveRadioCircle"; $band = "5.8GHz"; $AssignedLayer = 'fiveGHzStations'; break; case "900MHz": // Note: Channel values borked for 900Mhz $icon = "nineRadioCircle"; $band = "900MHz"; $AssignedLayer = 'nineHundredMHzStations'; break; default: // unknown $icon = "unknownRadioCircle"; $band = "?"; $AssignedLayer = 'otherStations'; } } /* * check for Out of Date Firmware */ switch ($node_FirmwareStatus) { case 1: $firmware = "Firmware: " . $node_info['firmware_version'] . ""; break; case 2: $firmware = "Firmware: " . $node_info['firmware_version'] . ""; break; default: $firmware = $node_info['firmware_version']; } /* * Now build the marker */ if ($node_ServiceList) { $node_ServiceList = "
Services:" . $node_ServiceList; } if ($node_LinkedList) { $node_LinkedList = "
Linked to:
Node Name (cost to/from) distance bearing

" . $node_LinkedList; } $markerList .= "L.marker([" . $node_info['lat'] . "," . $node_info['lon'] . "], {title: '" . $node_info['node'] . "', icon: " . $icon . "}).bindPopup(\" " . $nodeUrl . " (" . $band . ")
" . $node_info['lat'] . ", " . $node_info['lon'] . "
SSID: " . $node_info['ssid'] . "
Channel: " . $node_info['channel'] . ", Bandwidth: " . $node_info['chanbw'] . "
" . $node_info['model'] . "
" . $firmware . $node_ServiceList . $node_LinkedList . "\").addTo(" . $AssignedLayer . ") ,\n"; // Close out this node /* * If Upgrade Suggested add Node to that layer */ if ($node_FirmwareStatus > 0) { $markerList .= "L.marker([" . $node_info['lat'] . "," . $node_info['lon'] . "], {title: '" . $node_info['node'] . "', icon: " . (($node_FirmwareStatus == 1) ? "redCircle" : "orangeCircle") . "}).bindPopup(\" " . $nodeUrl . " (" . $band . ")
" . $node_info['model'] . "
" . $firmware . "
" . (($node_FirmwareStatus == 1) ? "Software upgrade is highly recommended" : "Experimental") . " \").addTo(upgradeStations) ,\n"; } return $markerList; } /** * buildStationMarker * This routine builds Station Markers. Station Markers are auxiliary (non-mesh) details to be displayed on the map. * These markers are added to the "Other Stations" layer. * The currently defined Station Markers are: * Operator, Police Station, Fire Station, EOC, Hospital, Other * * Station Markers are stored in the station_info table. Station Markers are manually created. * * @param $station_info * * @return string AssignedLayer */ function buildStationMarker($Marker) { //Now we look at the 'channel' value, for each node, from the node_info database. //Then compare it to what we know about each bands channels //if we find a match, we assume we're in that band... switch ($Marker['type']) { case "operator": // Operator Home Station $icon = "operatorIcon"; $AssignedLayer = 'operatorsElements'; break; case "police": $icon = "policeIcon"; $AssignedLayer = 'policeElements'; break; case "eoc": $icon = "eocIcon"; $AssignedLayer = 'racesElements'; break; case "firedepartment": $icon = "fireIcon"; $AssignedLayer = 'fireElements'; break; case "hospital": $icon = "hospitalIcon"; $AssignedLayer = 'hospitalElements'; break; default: // unknown $icon = "Red_Marker"; $AssignedLayer = 'otherElements'; } /* * Now build the marker */ $markerList = "L.marker([" . $Marker['lat'] . "," . $Marker['lon'] . "], {title: '" . $Marker['name'] . "', icon: " . $icon . "}).bindPopup(\" " . $Marker['name'] . "
" . $Marker['description'] . "
" . $Marker['lat'] . ", " . $Marker['lon'] . "
TYPE: " . $Marker['type'] . "\") .addTo(" . $AssignedLayer . ") ,\n"; return $markerList; } /* * DATABASE access routines **********************************************************************************************************************/ /** * load the Node data into an array. * * Where Clause and Orderby are optional * @param null $whereClause * @param null $orderBy * * @return array */ function load_Nodes($whereClause = null, $orderBy = null) { /* * Node Table Query */ global $USER_SETTINGS; global $useNodes; $NodeList = array(); if (isset($USER_SETTINGS['sql_db_tbl_node'])) { // Setup the Query ( replace WHERE and ORDER By as needed ) $query = "SELECT * FROM " . $USER_SETTINGS['sql_db_tbl_node'] . " " . ($whereClause ? $whereClause : " WHERE 1=1 ") . " " . ($orderBy ? $orderBy : " ORDER BY node"); // Retrieve the data $node_info_db = mysqli_query($GLOBALS['sql_connection'], $query) or die('Could not Select Items from Node Table: ' . mysqli_error()); // Load the data into an array for ease of handling while ($node_info = mysqli_fetch_array($node_info_db, MYSQLI_ASSOC)) { $NodeList[] = $node_info; } $useNodes = true; } else { $useNodes = false; } return $NodeList; } /** * load the Marker data into an array. * * Where Clause and Orderby are optional * @param null $whereClause * @param null $orderBy * * @return array */ function load_Markers($whereClause = null, $orderBy = null) { /* * marker Table Query */ global $USER_SETTINGS; global $useMarkers; $MarkerList = array(); if (isset($USER_SETTINGS['sql_db_tbl_marker'])) { // Setup the Query ( replace WHERE and ORDER By as needed ) $query = "SELECT * FROM " . $USER_SETTINGS['sql_db_tbl_marker'] . " " . ($whereClause ? $whereClause : " WHERE 1=1 ") . " " . ($orderBy ? $orderBy : " ORDER BY name"); // Retrieve the data $marker_info_db = mysqli_query($GLOBALS['sql_connection'], $query) or die('Could not Select Items from marker Table: ' . mysqli_error()); // Load the data into an array for ease of handling while ($marker_info = mysqli_fetch_array($marker_info_db, MYSQLI_ASSOC)) { $MarkerList[] = $marker_info; } $useMarkers = true; } else { $useMarkers = false; } return $MarkerList; } /** * load the Topology (or Link) Data into an array. * * Where Clause and Orderby are optional * @param null $whereClause * @param null $orderBy * * @return array */ function load_Topology($whereClause = null, $orderBy = null) { /* * Topology Table Query */ global $USER_SETTINGS; global $useLinks; $TopoList = array(); if (isset($USER_SETTINGS['sql_db_tbl_topo'])) { // Setup the Query ( replace WHERE and ORDER By as needed ) $query = "SELECT * FROM " . $USER_SETTINGS['sql_db_tbl_topo'] . " " . ($whereClause ? $whereClause : " WHERE 1=1 ") . " " . ($orderBy ? $orderBy : " ORDER BY distance, cost"); // Retrieve the data $topology_info_db = mysqli_query($GLOBALS['sql_connection'], $query) or die('Could not Select Items from Topology Table: ' . mysqli_error()); // Load the data into an array for ease of handling while ($topology_info = mysqli_fetch_array($topology_info_db, MYSQLI_ASSOC)) { $TopoList[] = $topology_info; } $useLinks = true; } else { $useLinks = false; } return $TopoList; } /* * HTML Page Setup routines **********************************************************************************************************************/ /** * add_MapLayers * * This routine adds the MapLayers needed * the (navigator.online) controls the display for online or offline browsers * No it doesn't, it doesn't tell you crap really... being on a LAN makes navigator.onLine true!!! * It has no bearing whatsoever if internet access is available or not * * * @return string - This string will need to be outputed to the browser */ function add_MapLayers() { if($GLOBALS['mesh']) { $offline_map_tiles = $GLOBALS['USER_SETTINGS']['offlineMapTileDir']; $Content = <<< EOD // navigator.onLine *DOES NOT* work!! var offlineMapTiles = "$offline_map_tiles/{z}/{x}/{y}.png"; var defaultMap = new L.tileLayer(offlineMapTiles); var baseLayers = {"Offline Map": defaultMap}; \n\n EOD; }else { $Content = <<< EOD //if (navigator.onLine) <-- *DOES NOT* work. REMOVED var OSMMapURL = '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; var terrainMapURL = '//stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.jpg'; var topoMapURL = '//{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; var OSMmap = new L.tileLayer(OSMMapURL); var defaultMap = new L.tileLayer(terrainMapURL); var topologyMap = new L.tileLayer(topoMapURL); var baseLayers = {"Topographic": topologyMap, "Street": OSMmap, "Terrain": defaultMap}; \n\n EOD; } return $Content; } /** * @param $numNodes * @param $numLinks * @param $numMarkers * * @return string */ function add_MapImages($numNodes, $numLinks, $numMarkers) { global $MESH_SETTINGS; $Content = " // Node and Link Icons var greenRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_Default'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); // Out of Date node software var redCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_OOD'] . "', iconSize: [22, 22], iconAnchor: [11, 11], popupAnchor: [0, -9] }); // Experiment node software var orangeCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_Experimental'] . "', iconSize: [22, 22], iconAnchor: [11, 11], popupAnchor: [0, -9] }); // 900 Mhz var nineRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_900MHz'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); //2.4GHz var twoRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_24GHz'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); //3GHz var threeRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_3GHz'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); //5GHz var fiveRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_5GHz'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); //Unknown var unknownRadioCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_Unknown'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] }); //a special one var linuxCircle = L.icon({ iconUrl: '" . $MESH_SETTINGS['Device_Linux'] . "', iconSize: [18, 18], iconAnchor: [9, 9], popupAnchor: [0, -9] });\n"; if ($numMarkers > 0) { $Content .= " // Marker Icons var policeIcon = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_Police'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] }); var fireIcon = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_Fire'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] }); var operatorIcon = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_Operator'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] }); var hospitalIcon = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_Hospital'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] }); var eocIcon = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_EOC'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] }); var Red_Marker = L.icon({ iconUrl: '" . $MESH_SETTINGS['Marker_Future'] . "', iconSize: [25, 25], iconAnchor: [9, 9], popupAnchor: [0, -9] });\n\n"; } return $Content; } /** * @param $numNodes * @param $numLinks * @param $numMarkers * * @return string */ function create_MapLayers($numNodes, $numLinks, $numMarkers) { //overlay groups to help superposition order $Content = " // Node Groups var nineHundredMHzStations = new L.LayerGroup(); var twoGHzStations = new L.LayerGroup(); var threeGHzStations = new L.LayerGroup(); var fiveGHzStations = new L.LayerGroup(); var otherStations = new L.LayerGroup(); var upgradeStations = new L.LayerGroup();\n "; if ($numLinks > 0) { $Content .= " // Link Groups var rfLinks = new L . LayerGroup(); var tunnelLinks = new L . LayerGroup(); var dtdLinks = new L . LayerGroup(); var infiniteLinks = new L . LayerGroup(); var stations = new L . LayerGroup(); var linkLines = new L . LayerGroup(); var legendLayer = new L . layerGroup();\n "; } if ($numMarkers > 0) { $Content .= " // Marker Groups var otherElements = new L . LayerGroup(); var policeElements = new L . LayerGroup(); var fireElements = new L . LayerGroup(); var hospitalElements = new L . LayerGroup(); var racesElements = new L . LayerGroup(); var operatorsElements = new L . LayerGroup(); var otherElements = new L . LayerGroup(); \n\n "; } return $Content; } /** * @param $numNodes * @param $numLinks * @param $numMarkers * * @return string */ function create_MapOverlays($numNodes, $numLinks, $numMarkers) { global $MESH_SETTINGS; $Content = "// Node Overlays var groupedOverlays = { \"Stations\": { \"2.4GHz\": twoGHzStations, \"3.4GHz\": threeGHzStations, \"5.8GHz\": fiveGHzStations, \"900MHz\": nineHundredMHzStations, \"Additional Mesh\": otherStations, \"Check Versions\": upgradeStations }"; if ($numLinks > 0) { $Content .= " ,\n // Link Overlays \"Links\": { \"RF Only\": rfLinks, \"DTD\": dtdLinks, \"Tunnels\": tunnelLinks, \"Infinite\": infiniteLinks }\n"; } if ($numMarkers > 0) { $Content .= " ,\n // Marker Layers \"Additional\": { \"Police\": policeElements, \"Fire Dept\": fireElements, \"Hospital\": hospitalElements, \"EOC\": racesElements, \"Operators\": operatorsElements, \"Future Mesh\": otherElements }\n"; } $Content .= "};\n\n"; return $Content; } /** * @return string */ function create_MapLegend() { //legend overlay $Content = <<< EOD var legend = L.control({position: 'topright'}); legend.onAdd = function (map) { var div = L.DomUtil.create('div', 'info legend', L.DomUtil.get('map')); div.innerHTML += 'legend
' + 'legend'; return div; };\n\n EOD; return $Content; } /** * @return string */ function create_MapImage() { global $USER_SETTINGS; //init the map with size, zoom level, center co-ords, etc... //http://leafletjs.com/reference-1.0.3.html#control-zoom $Content = " var map = L.map('mapid', { //attributionControl: false, center: [" . $USER_SETTINGS['map_center_coordinates'] . "], zoom: [" . $USER_SETTINGS['map_initial_zoom_level'] . "], minZoom: 0, maxZoom: 18, zoomSnap: 0, zoomDelta: 0.25, layers: [defaultMap, twoGHzStations, threeGHzStations, fiveGHzStations, nineHundredMHzStations, rfLinks, tunnelLinks, dtdLinks, infiniteLinks], fullscreenControl: true });\n\n "; return $Content; } /** * @param $numNodes * @param $numLinks * @param $numMarkers * * @return string */ function show_MapMarkerDetails($numNodes, $numLinks, $numMarkers, $numNodesTotal, $numLinksTotal) { // Get the last time we updated the link info $filetime = wxc_scriptGetLastDateTime("LINKINFO", "topology"); if ($filetime) { $filetime = date_format($filetime, 'F d Y H:i:s'); } //$Content = "MeshMapDetails = '" . $numNodes . " Nodes shown, with " . $numLinks . // " links " . "    Data Last Acquired @ " . $filetime . "';\n"; $Content = "MeshMapDetails = '" . $numNodes . " Nodes shown, with " . $numLinks . " links " . " | Data Last Acquired @ " . $filetime . "';\n"; $Content .= "WXCAttribution = 'Map originally created by KG6WXC Oct 2016 with N2MH and K6GSE contributions | ';\n"; $Content .= "MapAttribution = 'Leaflet ';\n"; $Content .= "attributionCtrl = map.attributionControl;\n"; $Content .= "attributionCtrl.setPrefix(WXCAttribution + MapAttribution);\n"; $Content .= "attributionCtrl.addAttribution(MeshMapDetails);\n"; return $Content; } /** * @return string */ function instantiate_Map() { $Content = <<< EOD var hash = new L.Hash(map); /* * MeshMap Legend */ legend.addTo(map); /* * Layer Control */ L.control.groupedLayers(baseLayers, groupedOverlays, {position: 'topleft'}).addTo(map); /* * Scale Control */ L.control.scale().addTo(map);\n /* Attribution */ //attributionCtrl({position: 'bottomleft'}).addTo(map);\n EOD; return $Content; } ?>