Kartendienste wie Open Street Map oder Google Map sind eine wirklich feine und praktische Sache. Schnell mal ein paar Koordinaten eintragen und anzeigen lassen, eine Route ausgeben und so weiter.

Was macht man aber, wenn man keinen Empfang hat, wie zum Beispiel auf hoher See oder irgendwo mitten in der Wildnis? Entweder greift man tief in die Tasche und besorgt sich eine Sattelitenverbindung oder man baut sich mit wenigen Handgriffen seinen eigenen, kleinen Kartenserver.

Die Sachen, die man dafür braucht, sind alle frei verfügbar - das wären Apache als Webserver, MapServer zum generieren der Grafiken und OpenLayers, um die Grafiken in eine WebSeite einzubauen. Desweiteren braucht man Shape-Dateien von dem Gebiet, von dem man den Kartendienst aufsetzen möchte.

Diese findet man in der Regel auch frei im Internet. Oder man holt sich die passenden Shape-Files von Open Street Map, die von GeoFabrik zur verfügung gestellt werden.
Diese Shape-Files sind allerdings sehr fein aufgelöst und man braucht dann schon ein wenig Rechenleistung, um diese in die gewünschten Bilder rendern zu lassen.

Ich habe jetzt für einen Freund so einen Kartendienst auf einem Raspberry installiert, den er dann mit an Bord nimmt und dort steht er per CrossLink-Kabel als Karten-Server für den Bord-Rechner zur Verfügung.

Ich beschreibe hier daher die Installation und Konfiguration auf einem Raspberry Pi.
Ein Beaglebone Black würde sich noch ein wenig besser eignen, da er die Möglichkeit bietet, sich mit dem Bord-Rechner per USB-Kabel zu verbinden und dann eine Ethernet-over-USB verbindung einzurichten, wodurch dann gleichzeitig die Stromversorgung gesichert wäre. Allerdings hab ich nur einen und den brauch ich hier ;-)

1. Software installieren
Also um jetzt den Karten-Server auf dem Raspberry aufzusetzen, muss man erstmal die nötige Software installieren:

apt-get install apache2 cgi-mapserver gdal-bin

2. Shape-Files besorgen
Dann besorgt man sich die gewünschten Shape-Files. Ich brauchte nur die Küstenlinien von Europa und habe dazu dieses Shape gefunden:

Europa

Dieses Shape ist gleichzeitig nicht zu hochauflösend und läuft daher auf dem Raspberry auch einigermaßen flüssig. Die Datei heißt zwar world.zip, ist aber wirklich nur Europa drauf :-)

Dann legt man in seinem Home-Verzeichnis einen Ordner für die Shape-Files an und entpackt diese in den Ordner.

mkdir /home/pi/shapes
mkdir /home/pi/shapes/eu
mv world.zip /home/pi/shapes/eu
cd /home/pi/shapes/eu
unzip world.zip

Danach sollten in diesem Verzeichnis folgende Dateien liegen:

pi@raspberrypi ~/shapes/eu $ ls -l
insgesamt 456
-rw-rw-r-- 1 pi pi   9062 Jul 14 19:54 MyEurope.dbf
-rw-rw-r-- 1 pi pi    145 Jul 14 19:54 MyEurope.prj
-rw-rw-r-- 1 pi pi    452 Jul 14 19:54 MyEurope.sbn
-rw-rw-r-- 1 pi pi    148 Jul 14 19:54 MyEurope.sbx
-rw-rw-r-- 1 pi pi 299032 Jul 14 19:54 MyEurope.shp
-rw-rw-r-- 1 pi pi   1795 Jul 14 19:54 MyEurope.shp.xml
-rw-rw-r-- 1 pi pi    364 Jul 14 19:54 MyEurope.shx
-rw-r--r-- 1 pi pi 131025 Jul 14 19:53 world.zip
pi@raspberrypi ~/shapes/eu $ 

3. MapServer konfigurieren
Der MapServer an sich muss nicht konfiguriert werden, sondern nur die Karten und Layer, die er darstellen soll. Die passiert mittels sogenannter Map-Files.
Um dieses Map-File nun richtig erstellen zu können, braucht man zuerst ein paar Informationen über das Shape.
Diese enthält man mit dem Befehl ogrinfo. Dieser ist Teil des gdal-bin-Pakets, welches ja schon mit installiert wurde. Also

pi@raspberrypi ~/shapes/eu $ ogrinfo MyEurope.shp
INFO: Open of `MyEurope.shp'
      using driver `ESRI Shapefile' successful.
1: MyEurope (Polygon) 

Dadurch erhält man erstmal Informationen darüber, welche Layer in diesem Shape enthalten sind. In diesem Fall ist es nur ein Layer mit dem dem Namen MyEurope. Jetzt braucht man noch Informationen zu diesem Layer.
Diese bekommt man mit

pi@raspberrypi ~/shapes/eu $ ogrinfo MyEurope.shp MyEurope -summary
INFO: Open of `MyEurope.shp'
      using driver `ESRI Shapefile' successful.

Layer name: MyEurope
Geometry: Polygon
Feature Count: 33
Extent: (-31.289030, 27.637497) - (30.128712, 69.060303)
Layer SRS WKT:
GEOGCS["GCS_WGS_1984",
    DATUM["WGS_1984",
        SPHEROID["WGS_84",6378137.0,298.257223563]],
    PRIMEM["Greenwich",0.0],
    UNIT["Degree",0.0174532925199433]]
FIPS_CNTRY: String (2.0)
GMI_CNTRY: String (3.0)
CNTRY_NAME: String (40.0)
SOVEREIGN: String (40.0)
POP_CNTRY: Integer (10.0)
SQKM_CNTRY: Real (12.3)
SQMI_CNTRY: Real (12.3)
CURR_TYPE: String (16.0)
CURR_CODE: String (4.0)
LANDLOCKED: String (1.0)
COLOR_MAP: String (1.0)
Pop2011CIA: Integer (9.0)
Pop2000Wik: Integer (9.0)
url: String (100.0)
pi@raspberrypi ~/shapes/eu $ 

Die drei Informationen, die man unbedingt für das Mapfile benötigt, sind Geometry, Extent und Layer SRS WKT. Hier steht bei Datum "WGS_84".
Jetzt können wir das erste, einfache Mapfile erstellen.
Dafür legen wir noch ein verzeichnis an und erstellen die Datei eu.map

mkdir /home/pi/maps
nano /home/pi/maps/eu.map

In diese Datei dann einfach den folgenden Code eintragen.

MAP
  # Der Name der Map. Dieser ist frei wählbar
  NAME "Europa"

  # der Pfad zu den Shape-Dateien
  SHAPEPATH "/home/pi/shapes/eu/"
  
  # Groeße von dem zu erzeugenden Bild
  SIZE 800 600

  # Die Extend-Werte aus dem Shape-File
  EXTENT -31.289030 27.637497 30.128712 69.060303
  
  # Typ von dem zu erzeugenden Bild. png hat den vorteil, dass es transparente Hindergruende darstellen kann
  IMAGETYPE PNG

        # Die Projektion des Shapes. Das Shape hatte als Datum "WGS_84", was epsg:4326 entspricht.
        # welchem epsg-Wert die Projektion eines Shapes entspricht, muss man im Internet suchen.
	PROJECTION
	  "init=epsg:4326"
	END
		 
	WEB
	    IMAGEPATH "/var/www/tmp/"
	    IMAGEURL  "/tmp/"
	    METADATA
	    	"wms_enable_request" "*"
	    END
	END

  # Hier werden dann die Layer definiert
  LAYER
    NAME europe
    DATA MyEurope
    STATUS ON
    # der Typ des Shapes - Ausgabe war POLYGON
    TYPE POLYGON
    
    PROJECTION
      "init=epsg:4326"
    END
    
    METADATA
      "wms_title"           "Küstenlinien Europa"
    END
    CLASS
      STYLE
        COLOR 0 0 0
        OUTLINECOLOR 0 0 0
      END
    END
  END
END

Diese Map-Files sind normalerweise sehr viel umfangreicher und beliebig kompliziert, aber für dieses Beispiel ist dieses Map-File schon völlig ausreichend. Weitere Informationen zu den Map-Fies findet man natürlich auf der homepage von MapServer.
Mit strg+o die Datei speichern und mit strg+x den Editor schließen. Das war es auch schon.
Zeit für einen ersten Test:

Wenn man dem Beispiel gefolgt ist und je nachdem, wo Apache und Mapserver installiert wurden, muss die Adresse noch angepasst werden - also etwas wie localhost oder IP des Raspberry.
Also Browser öffnen und in die Adresszeile folgenden Link eingeben:
http://ip-des-servers/cgi-bin/mapserv?map=/home/pi/maps/eu.map&SERVICE=W...

Und wenn alles geklappt hat, sollte nach kurzer Zeit folgendes Bild erscheinen.

[caption id="attachment_788" align="aligncenter" width="300"]Shapefile-Test Erster Test mit dem Mapserver[/caption]

Update:
Um den Request etwas übersichtlicher zu gestalten, indem man nicht jedes mal die map-Datei mit angeben muss, kann man folgende Option wählen (hier beschrieben für Debian / Ubuntu):
Man benennt die Datei mapserv im Verzeichnis cgi-bin um in den Namen seines WMS-Dienstes, also zum Beispiel

cp /usr/lib/cgi-bin/mapserv /usr/lib/cgi-bin/mein-wms

Dann mus man in der Konfigurationsdatei seines Webservers folgendes hinzufügen:
Für Apache die Datei /etc/apache2/sites-available/default.conf bzw. die entsprechende Datei
#MapServer Anwendungen
SetEnvIf Request_URI "/cgi-bin/mein-wms" map=/home/pi/maps/eu.map

Danach sieht der Request folgendermaßen aus:
http://ip-of-server/cgi-bin/my-wms?SERVICE=WMS&REQUEST=Getmap&VERSION=1....

Jetzt hat man schonmal eine Basiskarte. Diese ist aber noch völlig statisch. Um die Karte jetzt interaktiv zu machen und mit etwas Leben zu füllen, braucht man OpenLayers. Open Layers ist eine JavaScript-Bibliothek und entspricht eigentlich dem, was die Google-Maps-Api für Google ist.

Man baut sich also eine einfache HTML-Datei mit Open-Layers zusammen, und es kann los gehen:

 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 
<html> 
    <head>
    
        <style type="text/css">
            div.olControlMousePosition { color: red; }
        </style>
 
        <script type="text/javascript" src="http://openlayers.org/api/OpenLayers.js"></script> 
        <script type="text/javascript">
            function init(){
    
                var center = new OpenLayers.LonLat(10, 49.5);
    
                var map = new OpenLayers.Map( 'map' );

                var baseLayer = new OpenLayers.Layer.MapServer( "Europe Map", "http://ip-des-servers/cgi-bin/mapserv", {map: '/home/pi/maps/eu-test.map', layers: 'europe', srs: 'EPSG:4326', visibility: true } );

                map.addLayer(baseLayer);
                
                var markers = new OpenLayers.Layer.Markers( "Markers" );
                map.addLayer(markers);
                 
                 var myMarker = new OpenLayers.Marker(new OpenLayers.LonLat(13, 52.5));
                 //here add mouseover event
                myMarker.events.register('mouseover', myMarker, function(evt) {
                    popup = new OpenLayers.Popup.FramedCloud("Popup",
                        new OpenLayers.LonLat(13, 52.5),
                        null,
                        '<div>Hallo Welt. Gru&szlig; aus Berlin</div>',
                        null,
                        false);
                    map.addPopup(popup);
                });
                //here add mouseout event
                myMarker.events.register('mouseout', myMarker, function(evt) {popup.hide();});
                markers.addMarker(myMarker);


                map.addControl( new OpenLayers.Control.Zoom() );
                map.addControl(new OpenLayers.Control.MousePosition());
                map.setCenter( center, 4 );
            }
        </script> 
 
    </head> 
     
    <body onload="init()"> 
        <p><h1>Erstes Beispiel</h1><p>
        <div id="map" style="width:800px;height:600px"></div>
        
    </body> 
</html>

Wenn man diese HTML-Datei jetzt aufruft, sollte man dann etwas in der Art im Browser sehen:
Unsere Karte mit einer Zoom-Control oben links, einem Marker mit Popup und einer Anzeige der Mouse-Position unten rechts.

[caption id="attachment_797" align="aligncenter" width="300"]HTML-Beispiel mit OpenLayers Erstes HTML-Beispiel mit OpenLayers[/caption]

Jetzt kann man nach belieben weitere Marker, Layer oder was einem sonst noch einfällt der Karte hinzufügen.

"Live" sehen kann man das Endprodukt hier ( Race Tracker ). Als zusätzlichen WMS-Layer ist noch eine Karte von OpenWeatherMap eingebunden mit den aktuellen Windgeschwindigkeiten. Das ist ein Race-Tracker der Segel-Regatta Round Britain and Ireland .

Wegen Umbau ist der Server mit dem Race-Tracker im Moment nicht erreichbar

Weitere Informationen zu OpenLayers findet man auf openlayers.org

Comments

Fri, 06.11.2015 - 19:12

Hey

Sorry, unfortunately i'm not an expert in manipulating shape files, but in the map file the necessary part should be the layer definition. It should be something like

LAYER
STATUS ON
# Type of the Shape - output should then be POINT or something like that
TYPE POINT

Hope this helps

Bjoern

Tue, 31.10.2017 - 17:45

Hallo,

ich bin deiner Anleitung gefolgt und Sie war auch echt Top doch leider funktioniert das aufrufen der Karte nicht mehr.

"The requested URL /cgi-bin/my-wms was not found on this server." Kannst du mir helfen?

 

Tue, 31.10.2017 - 19:05

Hallo

Na ich kann es auf jeden Fall versuchen ;-)
Du bist also bis dahin gekommen, dass du die Datei
/usr/lib/cgi-bin/mapserv in
/usr/lib/cgi-bin/mein-wms
umbenannt hat.

Hast du danach die Apache Konfig Datei wie beschrieben angepasst?
Wenn ja, hast du danach den Apache neu gestartet?

Vielleicht kommst du damit schon weiter.

Gruß Bjoern

Wed, 01.11.2017 - 09:25

Hallo, ich hoffe das ich es richtig gemacht habe.

ich habe in dem Pfad /etc//apache2/sites-available eine Datei 000-default.conf und in dieser Datei habe ich am Ende die Zeile aus dem Tutorial eingefügt. Danach hab ich den Server neu gestartet.

Tue, 02.01.2018 - 13:59

Hallo Bjoern,
ich habe leider wenig Ahnung von HTML / Apache und brauche daher noch mal einen grundlegende Hintergrundinfo zu zwei Fragen.
Ich habe den RPi aufgesetzt und mit OpenLayers kann ich mir statisch eine Karte aus einer Shape Datei bzw. mehreren anzeigen lassen. Klappt anz gut!
Wie bekomme ich es hin, dass ich per redirection (oder wie auch immer) meine Seite sofort angezeigt bekomme?
Ich möchte den RPi als WLAN-Hotspot einrichten, so dass man sofort die entsprechende Seite angezeigt bekommt? So wie bei einem WLAN Gastzugang in öffentlichen Bereichen ...
Habe da schon einige Anleitungen zur Einrichtung als WLAN-Router oder Bridge gefunden, aber das ist ja nicht das was ich suche ...
Wie kann ich mit OpenLayers dann mehrere "bewegliche" Positionen anzeigen?
Ich könnte mit einer Software immer wieder HTML Dateien schreiben, welche die Positionen aktualisiert, aber wie erreiche ich es das diese Marker dann kontinuiertlich neu dargestelt werden?

Fri, 05.01.2018 - 00:21

Hallo Burkhard.

Ich hab jetzt nict alles verstanden, aber ich versuche mal zu antworten :-)
zu 1: du hast bei Apache eine DocumentRoot eingegeben .. das sollte etwas sein wie /var/www/ oder /srv/www/ ..
Wenn jemand ohne weitere Angaben auf deine Apache zugreift, guckt Apache erstmal dort nach und sucht nach einer Datei "index.html".
Wenn du also jetzt dafür sorgst, dass deine Datei, die die Karte darstellt - also http://deine-url/irgendwas/karte.html - in deiner DocumentRoot als index.html liegt, wird das für jeden, der auf deinen Server geht, als Startseite angezeigt.

Alternativ kannst du in deiner index.html im Bereich <head> ... </head> eine Zeile einfügen
<meta http-equiv="refresh" content="0; url=http://example.com/" />

Das sollte dafür sorgen, dass jeder von deiner "Startseite" auf deine Karte weitergeleitet.

Zu 2: Das ist dann schon ein wenig komplizierter daher hier nur eine Skizze: Im Prinzip musst du dafür sorgen, dass die Koordinaten deiner Marker per Javascript nachgeladen und dann auf der Karte dargestellt werden.
Außerdem musst du natürlich dafür sorgen, dass irgendwer dann die aktuellen Koordinaten in die richtige Datei schreibt, so dass sie nachgeledan werden können.

Ich hoffe, ich konnte helfen und du kommst so erstmal weiter.

Gruß Bjoern

Add comment

Please insert your mail adress. Your mail address will not be displayed.