geomap support

This commit is contained in:
Nils Schneider 2012-05-12 16:44:27 +02:00
parent 5d203b0f07
commit f05e6a3a26
71 changed files with 649 additions and 8 deletions

37
bat2geomap.py Normal file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env python
# TODO
# Gatewayliste
# aliases.json
import json
import fileinput
import argparse
from nodedb import NodeDB
from geomapbuilder import GeoMapBuilder
parser = argparse.ArgumentParser()
parser.add_argument('-a', '--aliases',
help='read aliases from FILE',
metavar='FILE')
parser.add_argument('batmanjson', help='output of batman vd json')
args = parser.parse_args()
options = vars(args)
db = NodeDB()
db.import_batman(list(fileinput.input(options['batmanjson'])))
if options['aliases']:
db.import_aliases(json.load(open(options['aliases'])))
db.import_wikigps("http://freifunk.metameute.de/Knoten")
m = GeoMapBuilder(db)
print(m.build())

113
geomapbuilder.py Normal file
View file

@ -0,0 +1,113 @@
class GeoMapBuilder:
kml_template = """<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Style id="virtual-link">
<LineStyle>
<color>#4f0013f8</color>
<width>2</width>
</LineStyle>
</Style>
<Style id="wifi-link">
<LineStyle>
<color>#ff13d854</color>
<width>4</width>
</LineStyle>
</Style>
<Style id="router-unknown">
<IconStyle>
<Icon>
<href>router-unknown.png</href>
<scale>1.0</scale>
</Icon>
</IconStyle>
</Style>
<Style id="router-up">
<IconStyle>
<Icon>
<href>router-up.png</href>
<scale>1.0</scale>
</Icon>
</IconStyle>
</Style>
<Style id="router-down">
<IconStyle>
<Icon>
<href>router-down.png</href>
<scale>1.0</scale>
</Icon>
</IconStyle>
</Style>
%s
</Document>
</kml>"""
def __init__(self, db):
self._db = db
def build(self):
text = []
nodes = self._db.get_nodes()
for node in nodes:
try:
text.append(GeoNode(node).render())
except:
continue
for link in self._db.get_links():
try:
text.append(GeoEdge(nodes, link).render())
except:
continue
return self.kml_template % "".join(text)
def gps_format(s):
return ",".join(s.split(" ")[::-1])
class GeoNode:
kml_template = """<Placemark>
<name>%s</name>
<styleUrl>#router-%s</styleUrl>
<Point>
<coordinates>%s,0</coordinates>
</Point>
<description>%s</description>
</Placemark>"""
def __init__(self, node):
self._node = node
def render(self):
if not self._node.gps:
raise
name = self._node.name
status = "up" if self._node.online else "down"
gps = gps_format(self._node.gps)
text = " ".join(self._node.macs)
return self.kml_template % (name, status, gps, text)
class GeoEdge:
kml_template = """<Placemark>
<LineString>
<coordinates>%s,0. %s,0.</coordinates>
</LineString>
<styleUrl>#%s</styleUrl>
</Placemark>"""
def __init__(self, nodes, link):
self._link = link
self.pair = [nodes[k] for k in link.pair]
def render(self):
if not (self.pair[0].gps and self.pair[1].gps):
raise
a = gps_format(self.pair[0].gps)
b = gps_format(self.pair[1].gps)
return self.kml_template % (a, b, "wifi-link")

122
html/geomap.html Normal file
View file

@ -0,0 +1,122 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="theme/default/style.css" type="text/css" />
<style type="text/css">
#map {
width: 100%;
height: 100%;
}
.olPopup p { margin:0px; }
</style>
<title>Freifunk Lübeck - Knotenkarte</title>
<script src="http://maps.burningsilicon.net/OpenLayers-2.8/OpenLayers.js"></script>
<script src="http://maps.burningsilicon.net/OpenLayers-2.8/cloudmade.js"></script>
<script src="http://maps.burningsilicon.net/OpenLayers-2.8/OpenStreetMap.js"></script>
<script type="text/javascript">
var map;
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control);
function init()
{
map = new OpenLayers.Map ("map", {
controls:[
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.LayerSwitcher(),
new OpenLayers.Control.Attribution(),
new OpenLayers.Control.Permalink(),
new OpenLayers.Control.ScaleLine(),
new OpenLayers.Control.OverviewMap(),
new OpenLayers.Control.MousePosition()],
maxResolution: 156543.0399,
numZoomLevels: 19,
units: 'm',
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326")
} );
var layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
map.addLayer(layerMapnik);
var layerTilesAtHome = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
map.addLayer(layerTilesAtHome);
var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");
map.addLayer(layerCycleMap);
var center = new OpenLayers.LonLat(153.02775, -27.47558).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
var zoom = 11
map.setCenter(center, zoom);
vectorLayer = new OpenLayers.Layer.GML("KML", 'geomap.kml',
{
projection: new OpenLayers.Projection("EPSG:4326"),
eventListeners: { 'loadend': kmlLoaded },
format: OpenLayers.Format.KML,
formatOptions: {
style: {strokeColor: "green", strokeWidth: 5, strokeOpacity: 0.5},
extractStyles: true,
maxDepth: 2,
extractAttributes: true
}
});
map.addLayer(vectorLayer);
selectControl = new OpenLayers.Control.SelectFeature(map.layers[3],
{onSelect: onFeatureSelect, onUnselect: onFeatureUnselect});
map.addControl(selectControl);
selectControl.activate();
var click = new OpenLayers.Control.Click();
map.addControl(click);
click.activate();
}
function onPopupClose(evt)
{
selectControl.unselect(selectedFeature);
}
function onFeatureSelect(feature)
{
selectedFeature = feature;
popup = new OpenLayers.Popup.FramedCloud("chicken",
feature.geometry.getBounds().getCenterLonLat(),
new OpenLayers.Size(100,150),
"<div style='font-size:.8em'><b>Name:</b>"+feature.attributes.name+"<br><b>Description:</b>"+feature.attributes.description+"</div>",
null, true, onPopupClose);
feature.popup = popup;
map.addPopup(popup);
}
function onFeatureUnselect(feature)
{
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
function kmlLoaded()
{
map.zoomToExtent(vectorLayer.getDataExtent());
}
</script>
</head>
<body onload="init()">
<h1>luebeck.freifunk.net</h1>
<ul>
<li><a href="nodes.html">Knotengraph</a></li>
<li><a href="geomap.html">Knotenkarte</a></li>
</ul>
<h2>Knotenkarte</h2>
<div id="map"></div>
</body>

BIN
html/img/blank.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 B

BIN
html/img/cloud-popup-relative.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
html/img/east-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

BIN
html/img/marker-blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

BIN
html/img/marker-gold.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 B

BIN
html/img/marker-green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
html/img/marker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
html/img/north-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
html/img/slider.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

BIN
html/img/south-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

BIN
html/img/west-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

BIN
html/img/zoom-plus-mini.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
html/img/zoombar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

View file

@ -2,9 +2,16 @@
<html> <html>
<head> <head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>freifunk.luebeck.net nodes</title> <title>Freifunk Lübeck - Knotengraph</title>
</head> </head>
<body> <body>
<h1>luebeck.freifunk.net</h1>
<ul>
<li><a href="nodes.html">Knotengraph</a></li>
<li><a href="geomap.html">Knotenkarte</a></li>
</ul>
<h2>Knotenkarte</h2>
<div id="map"></div>
<div id='chart'> </div> <div id='chart'> </div>
<link href='force.css' rel='stylesheet' type='text/css' /> <link href='force.css' rel='stylesheet' type='text/css' />
<script type="text/javascript" src="d3.js"></script> <script type="text/javascript" src="d3.js"></script>

BIN
html/router-down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
html/router-unknown.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
html/router-up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

View file

@ -0,0 +1,9 @@
.olLayerGoogleCopyright {
right: 3px;
bottom: 2px;
}
.olLayerGooglePoweredBy {
left: 2px;
bottom: 2px;
}

View file

@ -0,0 +1,7 @@
.olControlZoomPanel div {
background-image: url(img/zoom-panel-NOALPHA.png);
}
.olControlPanPanel div {
background-image: url(img/pan-panel-NOALPHA.png);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,343 @@
div.olMap {
z-index: 0;
padding: 0px!important;
margin: 0px!important;
cursor: default;
}
div.olMapViewport {
text-align: left;
}
div.olLayerDiv {
-moz-user-select: none;
}
.olLayerGoogleCopyright {
left: 2px;
bottom: 2px;
}
.olLayerGooglePoweredBy {
left: 2px;
bottom: 15px;
}
.olControlAttribution {
font-size: smaller;
right: 3px;
bottom: 4.5em;
position: absolute;
display: block;
}
.olControlScale {
right: 3px;
bottom: 3em;
display: block;
position: absolute;
font-size: smaller;
}
.olControlScaleLine {
left: 10px;
bottom: 15px;
font-size: xx-small;
}
.olControlScaleLineBottom {
border: solid 2px black;
border-bottom: none;
margin-top:-2px;
text-align: center;
}
.olControlScaleLineTop {
border: solid 2px black;
border-top: none;
text-align: center;
}
.olControlPermalink {
right: 3px;
bottom: 1.5em;
display: block;
position: absolute;
font-size: smaller;
}
div.olControlMousePosition {
bottom: 0em;
right: 3px;
display: block;
position: absolute;
font-family: Arial;
font-size: smaller;
}
.olControlOverviewMapContainer {
position: absolute;
bottom: 0px;
right: 0px;
}
.olControlOverviewMapElement {
padding: 10px 18px 10px 10px;
background-color: #00008B;
-moz-border-radius: 1em 0 0 0;
}
.olControlOverviewMapMinimizeButton {
right: 0px;
bottom: 80px;
}
.olControlOverviewMapMaximizeButton {
right: 0px;
bottom: 80px;
}
.olControlOverviewMapExtentRectangle {
overflow: hidden;
background-image: url("img/blank.gif");
cursor: move;
border: 2px dotted red;
}
.olControlOverviewMapRectReplacement {
overflow: hidden;
cursor: move;
background-image: url("img/overview_replacement.gif");
background-repeat: no-repeat;
background-position: center;
}
.olLayerGeoRSSDescription {
float:left;
width:100%;
overflow:auto;
font-size:1.0em;
}
.olLayerGeoRSSClose {
float:right;
color:gray;
font-size:1.2em;
margin-right:6px;
font-family:sans-serif;
}
.olLayerGeoRSSTitle {
float:left;font-size:1.2em;
}
.olPopupContent {
padding:5px;
overflow: auto;
}
.olControlNavToolbar {
width:0px;
height:0px;
}
.olControlNavToolbar div {
display:block;
width: 28px;
height: 28px;
top: 300px;
left: 6px;
position: relative;
}
.olControlNavigationHistory {
background-image: url("img/navigation_history.png");
background-repeat: no-repeat;
width: 24px;
height: 24px;
}
.olControlNavigationHistoryPreviousItemActive {
background-position: 0px 0px;
}
.olControlNavigationHistoryPreviousItemInactive {
background-position: 0px -24px;
}
.olControlNavigationHistoryNextItemActive {
background-position: -24px 0px;
}
.olControlNavigationHistoryNextItemInactive {
background-position: -24px -24px;
}
.olControlNavToolbar .olControlNavigationItemActive {
background-image: url("img/panning-hand-on.png");
background-repeat: no-repeat;
}
.olControlNavToolbar .olControlNavigationItemInactive {
background-image: url("img/panning-hand-off.png");
background-repeat: no-repeat;
}
.olControlNavToolbar .olControlZoomBoxItemActive {
background-image: url("img/drag-rectangle-on.png");
background-color: orange;
background-repeat: no-repeat;
}
.olControlNavToolbar .olControlZoomBoxItemInactive {
background-image: url("img/drag-rectangle-off.png");
background-repeat: no-repeat;
}
.olControlEditingToolbar {
float:right;
right: 0px;
height: 30px;
width: 200px;
}
.olControlEditingToolbar div {
background-image: url("img/editing_tool_bar.png");
background-repeat: no-repeat;
float:right;
width: 24px;
height: 24px;
margin: 5px;
}
.olControlEditingToolbar .olControlNavigationItemActive {
background-position: -103px -23px;
}
.olControlEditingToolbar .olControlNavigationItemInactive {
background-position: -103px -0px;
}
.olControlEditingToolbar .olControlDrawFeaturePointItemActive {
background-position: -77px -23px;
}
.olControlEditingToolbar .olControlDrawFeaturePointItemInactive {
background-position: -77px -0px;
}
.olControlEditingToolbar .olControlDrawFeaturePathItemInactive {
background-position: -51px 0px;
}
.olControlEditingToolbar .olControlDrawFeaturePathItemActive {
background-position: -51px -23px;
}
.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive {
background-position: -26px 0px;
}
.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive {
background-position: -26px -23px ;
}
.olControlSaveFeaturesItemActive {
background-image: url(img/save_features_on.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlSaveFeaturesItemInactive {
background-image: url(img/save_features_off.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olHandlerBoxZoomBox {
border: 2px solid red;
position: absolute;
background-color: white;
opacity: 0.50;
font-size: 1px;
filter: alpha(opacity=50);
}
.olHandlerBoxSelectFeature {
border: 2px solid blue;
position: absolute;
background-color: white;
opacity: 0.50;
font-size: 1px;
filter: alpha(opacity=50);
}
.olControlPanPanel {
top: 10px;
left: 5px;
}
.olControlPanPanel div {
background-image: url(img/pan-panel.png);
height: 18px;
width: 18px;
cursor: pointer;
position: absolute;
}
.olControlPanPanel .olControlPanNorthItemInactive {
top: 0px;
left: 9px;
background-position: 0px 0px;
}
.olControlPanPanel .olControlPanSouthItemInactive {
top: 36px;
left: 9px;
background-position: 18px 0px;
}
.olControlPanPanel .olControlPanWestItemInactive {
position: absolute;
top: 18px;
left: 0px;
background-position: 0px 18px;
}
.olControlPanPanel .olControlPanEastItemInactive {
top: 18px;
left: 18px;
background-position: 18px 18px;
}
.olControlZoomPanel {
top: 71px;
left: 14px;
}
.olControlZoomPanel div {
background-image: url(img/zoom-panel.png);
position: absolute;
height: 18px;
width: 18px;
cursor: pointer;
}
.olControlZoomPanel .olControlZoomInItemInactive {
top: 0px;
left: 0px;
background-position: 0px 0px;
}
.olControlZoomPanel .olControlZoomToMaxExtentItemInactive {
top: 18px;
left: 0px;
background-position: 0px -18px;
}
.olControlZoomPanel .olControlZoomOutItemInactive {
top: 36px;
left: 0px;
background-position: 0px 18px;
}
.olPopupCloseBox {
background: url("img/close.gif") no-repeat;
cursor: pointer;
}
.olFramedCloudPopupContent {
padding: 5px;
overflow: auto;
}
.olControlNoSelect {
-moz-user-select: none;
}
/**
* Cursor styles
*/
.olCursorWait {
cursor: wait;
}
.olDragDown {
cursor: move;
}
.olDrawBox {
cursor: crosshair;
}
.olControlDragFeatureOver {
cursor: move;
}
.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown {
cursor: -moz-grabbing;
}

View file

@ -2,10 +2,12 @@
DEST=$1 DEST=$1
GWS=`/usr/sbin/batctl gwl -n | tail -n +2 | sed 's/=>//' | awk '{ print $1 }'|while read a;do echo -n "-g $a ";done`
mkdir $DEST GWS=`(/usr/sbin/batctl gwl -n | tail -n +2 | grep -v '^No' | sed 's/=>//' | awk '{ print $1 }') | while read a; do echo -n "-g $a "; done`
cp html/* $DEST/ /usr/sbin/batctl vd json | python "$(dirname "$0")"/bat2nodes.py -a "$(dirname "$0")"/aliases.json $GWS - > $DEST/nodes.json.new
/usr/sbin/batctl vd json | python "$(dirname "$0")"/bat2geomap.py -a "$(dirname "$0")"/aliases.json - > $DEST/geomap.kml.new
mv $DEST/nodes.json.new $DEST/nodes.json
mv $DEST/geomap.kml.new $DEST/geomap.kml
ssh 188.138.99.158 batctl vd json|python ./bat2nodes.py -a aliases.json $GWS - > $DEST/nodes.json

View file

@ -12,7 +12,7 @@ class Node():
# 3 TT # 3 TT
def add_mac(self, mac): def add_mac(self, mac):
self.macs.add(mac) self.macs.add(mac.lower())
def __repr__(self): def __repr__(self):
return self.macs.__repr__() return self.macs.__repr__()

View file

@ -21,7 +21,7 @@ class NodeDB:
def maybe_node_by_mac(self, macs): def maybe_node_by_mac(self, macs):
for node in self._nodes: for node in self._nodes:
for mac in macs: for mac in macs:
if mac in node.macs: if mac.lower() in node.macs:
return node return node
raise raise
@ -171,9 +171,10 @@ class NodeDB:
for pair in zip(macs, gps): for pair in zip(macs, gps):
try: try:
node = self.maybe_node_by_mac(pair[0]) node = self.maybe_node_by_mac((pair[0], ))
except: except:
node = Node() node = Node()
node.add_mac(pair[0])
self._nodes.append(node) self._nodes.append(node)
node.gps = pair[1] node.gps = pair[1]