Récepteur ADS-B sur Raspberry Pi

Parce que les applications du Raspberry Pi sont illimités...

Modérateur : Francois

Répondre
sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » sam. 9 mai 2015 21:56

je pense aussi que ça vient de l'antenne.

Perso, celle-ci donne de bon résultats :
Image

L'antenne ads-b que j'utilise sur la 2nd installation (prise sur ebay), est pas mal aussi sur la bande aérienne.
Mais j'en ai trouvé une pas cher sur ebay pour la bande aérienne. Pas encore reçue. J’espère qu'elle me donnera de meilleurs résultats.
Et elle devrait normalement faire aussi pour recevoir les satellites météo NOAA :)

Bon sinon, toujours sur la thématique Google Earth, un petit logiciel sympas : adsb2kml

Faut d'abord installer les logiciels nécessaires :

Code : Tout sélectionner

apt-get update
apt-get install ruby ruby-dev rubygems build-essential
une fois ceci fait, faut installer les paquets suivants :

Code : Tout sélectionner

gem install ruby_kml
gem install sinatra
gem install adsb2kml
Ce qui est très long ! une fois la commande "gem" lancée, rien ne se passe. C'est normal. Tout se passe en tache de fond. Faut patienter.

ensuite :

Code : Tout sélectionner

git clone https://github.com/qwertos/adsb2kml.git

faut ensuite renommer le fichier config.rb.example en config.rb
Ensuite, ça se complique un peu.
En effet adsb2kml ne supporte que les messages au format SBS1.
Les messages envoyés par Modesdeco2 ne sont pas supportés (via l'argument --msg 30003). De même que pour la version de MalcolmRobb de dump1090

Je pense que ceci est du au fait que les messages ne sont pas au bon fomat.
exemple de message :

Code : Tout sélectionner

MSG,3,111,11111,0A0077,111111,2015/05/09,20:38:48.008,2015/05/09,20:38:47.977,,37000,,,42.31408,5.61088,,,,,,0
Je pense qu'Il faudrait modifier le fichier suivant :

Code : Tout sélectionner

/adsb2kml/lib/adsb2kml.rb
$MESSAGE_FORMAT = /^(?<type>(MSG|STA|ID|AIR|SEL|CLK)),(?<subtype>(1|2|3|4|5|6|7|8)?),\w*,(?<session_id>\d*),(?<aircraft_id>\d*),(?<address>\h{6}),(?<flight_id>\d*),\w*,\w*,\w*,\w*,(?<callsign>(\w|\s)*),(?<altitude>\d*),(?<speed>\d*),(?<track>\d*),(?<latitude>(-?\d{1,3}\.\d{5})?),(?<longitude>(-?\d{1,3}\.\d{5})?),(?<vert_rate>-?\d*),(?<squawk>\d*),(?<alert>\d*),(?<emergency>\d*),(?<ident>\d*),(?<ground>\d*)$/

	$STRING_FORMAT = "%10s %10s %10s %10s %10s %10s %10s %10s\n"

pour prendre en compte le bon format. Malheureusement, je n'y connais rien en programmation.
Si quelqu'un peut y jeter un coup d'oeil :)

En attendant que quelqu'un modifie le code, voici comment faire avec la version de dump1090 originale :

Code : Tout sélectionner

renommer votre répertoire dump1090 si celui-ci existe
ensuite :
git clone https://github.com/antirez/dump1090.git
cd dump1090
make
et lancer le avec la commande :
./dump1090 --enable-agc --gain 49.6 --net --interactive --aggressive --net-sbs-port 30003
ensuite, faut modifier le fichier

Code : Tout sélectionner

/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/geometry.rb

cherchez les lignes :
      def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.extrude(extrude) unless extrude.nil?
      xm.tessellate(tessellate) unless tessellate.nil?
      xm.altitudeMode(altitude_mode) if altitude_mode_set?
     end

et remplacer par :
      def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.extrude('1')
      xm.tessellate(tessellate) unless tessellate.nil?
      xm.altitudeMode ('absolute')
     end
dans une fenêtre de terminal

Code : Tout sélectionner

cd adsb2kml
ruby sin_fe.rb
après quelques instants, vous aurez :
Sinatra (v1.4.6) has taken the stage on 4567 for development with backup from WEBrick
Dans un navigateur, allez à l'adresse suivante :

Code : Tout sélectionner

http://adresse_ip_de_votre_framboise:4567/adsb.kml
vous aurez un fichier kml que vous pouvez charger dans Google Earth.
Problème, celui-ci ne se met pas à jour automatiquement.

2 solutions :
dans le bloc note, créez une fichier refresh.kml avec les lignes suivantes :

Code : Tout sélectionner

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
  <NetworkLink>
    <Link>
      <href>http://adresse_ip_de_votre_framboise:4567/adsb.kml</href>
      <refreshMode>onInterval</refreshMode>
      <refreshInterval>5</refreshInterval>
    </Link>
    </NetworkLink>
</Document>
</kml>
et chargez ce fichier dans Google Earth.

ou sinon, dans Google Earth, clic droit sur "Lieux Temporaires" => Ajouter => Lien Réseau
Dans Lien : http://adresse_ip_de_votre_framboise:4567/adsb.kml
Actualisation : Quand => Périodiquement => choisir la fréquence de rafraichissement

ça reviens au même :)

Petits soucis par contre :
- pas de trainés
- pas d'infos (altitude, vitesse...)

Je pense qu'il est possible de rajouter tout ça en éditant les fichiers dans : /var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml
Je n'ai malheureusement pas les connaissances en programmation nécessaire pour savoir comment faire.
Si quelqu'un souhaite y jeter un coup d’œil...

Voici le résultat dans Google Earth :
Image Image

et en changeant le logo de l'avion :
Image

Je vais voler des framboises :mrgreen: :lol:

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » dim. 10 mai 2015 00:29

bon, finalement je pense avoir trouver pour faire fonctionner adsb2kml avec modesdeco2 :D

lancer modesdeco2 avec l'argument --msg 30003

Code : Tout sélectionner

./modesdeco2 --gain 49.6 --agc --freq-correction 8 --web 8081 --beast 30006 --msg 30003 &
ensuite modifier le fichier /root/adsb2kml/lib/adsb2kml.rb comme suit :

Code : Tout sélectionner

require 'ruby_kml'

require_relative "ruby_kml/label_style.rb"

require_relative "adsb2kml/listener.rb"
require_relative "adsb2kml/database.rb"
require_relative "adsb2kml/airplane.rb"

module ADSB
	
	$MESSAGE_FORMAT = /^(?<type>(MSG|STA|ID|AIR|SEL|CLK)),(?<subtype>(1|2|3|4|5|6|7|8)?),(?<session_id>\d*),(?<aircraft_id>\d*),(?<address>\h{6}),(?<flight_id>\d*),(\d{1,4}\/\d{1,2}\/\d{1,2}),(\d{1,2}\:\d{1,2}\:\d{1,2}\.\d{1,3}),(\d{1,4}\/\d{1,2}\/\d{1,2}),(\d{1,2}\:\d{1,2}\:\d{1,2}\.\d{1,3}),(?<callsign>(\w|\s)*),(?<altitude>\d*),(?<speed>(-?\d{1,3}\.\d{1})?),(?<track>(-?\d{1,3}\.\d{1})?),(?<latitude>(-?\d{1,3}\.\d{6})?),(?<longitude>(-?\d{1,3}\.\d{6})?),(?<vert_rate>-?\d*),(?<squawk>\d*),(?<alert>\d*),(?<emergency>\d*),(?<ident>\d*),(?<ground>\d*)$/

	$STRING_FORMAT = "%10s %10s %10s %10s %10s %10s %10s %10s\n"
	

end
ce qui devrait prendre en compte une bonne partie des messages envoyés par modesdeco2

et ensuite :

Code : Tout sélectionner

ruby sin_fe.rb
reste plus qu'à trouver comment avoir les infos en overlay dans Google Earth maintenant :)


Edit :

Le code marche presque. Le logiciel drop les message quand les avions sont au sol (il s'agit du dernier paramètre du message) :

Code : Tout sélectionner

MSG,8,0,0,392DA7,0,2015/05/10,01:25:58.186,2015/05/10,01:25:58.186,,,,,,,,,,,,-1
Je crois que c'est le '-1' qu'il n'aime pas
Devrait pas être trop compliqué à modifier et le lui faire prendre en compte

Sinon pour les infos sur le vol, un moyen :

Code : Tout sélectionner

Modifier dans le fichier /var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/placemark.rb , les lignes suivantes :

def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Placemark {
        super
        features.each { |f| f.render(xm) }
        plain_children.each { |c| xm << c }
        geometry.render(xm) unless geometry.nil?
       xm.ExtendedData {
       xm.Data {
		
		xm.name ('Altitude')
		xm.value(1000)
        	 }

	xm.Data {
		xm.name ('Longitude')
		xm.value (1000)
		 }
       xm.Data {
		xm.name ('Latitude')
		xm.value (1000)
		 }	
}

      }

    
    end

Ce qui donne :
Image

Le problème étant de récupérer les bonnes valeurs
Elle sont générées dans /var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/point.rb
Il s'agit de la variable coordinates.
En particulier :

Code : Tout sélectionner

coordinates[0] pour la longitude
coordinates[1] pour la latitude
coordinates[2] pour l'altitude
Mon soucis étant de récupérer ces valeurs dans placemark.rb
ça à l'air d'être un problème de classe ou je sais trop quoi.
Quelqu'un s'y connait en programmation ?

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » dim. 10 mai 2015 15:25

Pour ceux intéressés, j'ai fini par réussir à faire ce que je voulais.
Le code est sûrement moche, mais il fonctionne :D

Déja, la modification de "/root/adsb2kml/lib/adsb2kml.rb" , qui devrait prendre en compte plus de messages :

Code : Tout sélectionner

require 'ruby_kml'

require_relative "ruby_kml/label_style.rb"

require_relative "adsb2kml/listener.rb"
require_relative "adsb2kml/database.rb"
require_relative "adsb2kml/airplane.rb"

module ADSB
	
	$MESSAGE_FORMAT = /^(?<type>(MSG|STA|ID|AIR|SEL|CLK)),(?<subtype>(1|2|3|4|5|6|7|8)?),(?<session_id>\d*),(?<aircraft_id>\d*),(?<address>\h{6}),(?<flight_id>\d*),(\d{1,4}\/\d{1,2}\/\d{1,2}),(\d{1,2}\:\d{1,2}\:\d{1,2}\.\d{1,3}),(\d{1,4}\/\d{1,2}\/\d{1,2}),(\d{1,2}\:\d{1,2}\:\d{1,2}\.\d{1,3}),(?<callsign>(\w|\s)*),(?<altitude>(\d*|-\d*)),(?<speed>(-?\d{1,3}\.\d{1})?),(?<track>(-?\d{1,3}\.\d{1})?),(?<latitude>(-?\d{1,3}\.\d{6})?),(?<longitude>(-?\d{1,3}\.\d{6})?),(?<vert_rate>-?\d*),(?<squawk>\d*),(?<alert>(\d*|-\d*)),(?<emergency>(\d*|-\d*)),(?<ident>(\d*|-\d*)),(?<ground>(\d*|-\d*))$/

	$STRING_FORMAT = "%10s %10s %10s %10s %10s %10s %10s %10s\n"
	

end
Ensuite, modification de "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/point.rb" comme suit :

Code : Tout sélectionner

# <Point id="ID">
#   <!-- specific to Point -->
#   <extrude>0</extrude>                   <!-- boolean -->
#   <tessellate>0</tessellate>             <!-- boolean -->
#   <altitudeMode>absolute</altitudeMode> 
#     <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
#   <coordinates>...</coordinates>         <!-- lon,lat[,alt] -->
# </Point>
module KML
  class Point < Geometry

    # A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order). 
    # Longitude and latitude values are in degrees, where:
    #
    # * longitude >= -180 and <= 180
    # * latitude >= -90 and <= 90
    # * altitude values (optional) are in meters above sea level
    
     def coordinates
      @coordinates
    end
     attr_accessor :coordinates

def coordinates_alt
      @@coordinates_alt
    end   

def coordinates_lat
      @@coordinates_lat
    end    

def coordinates_long
      @@coordinates_long
    end      
     


    # Set the coordinates
    def coordinates=(c)
      case c
      when String
        @coordinates = c.strip.split(',')
        unless @coordinates.length == 2 || @coordinates.length == 3
          raise "Coordinates string may only have 2 parts (indicating lat and long) or 3 parts (lat, long and altitude)"
        end
      when Array
        @coordinates = c
      when Hash
        @coordinates = [:lng, :lat, :alt].collect {|attr| c[attr]}.compact
	 
      else
        raise ArgumentError, "Coordinates must be either a String, Hash or an Array"
      end
	
    end
      

    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Point {
        super
        xm.coordinates(coordinates.join(","))
        @@coordinates_alt = (coordinates[2]) 
        @@coordinates_lat = (coordinates[1]) 
        @@coordinates_long = (coordinates[0])    

      }
    end

    def self.parse(node)
      self.new.parse(node)
    end
       

    def parse(node)
      super(node) do |cld|
        case cld.name
        when 'coordinates'
          self.coordinates = cld.content
        else
          puts "Point"
          p cld
          puts
        end
      end
      self
    end

  end
end
pour déclarer et définir 3 nouvelles variables

et ensuite modification de "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/placemark.rb"

Code : Tout sélectionner

module KML
  class Placemark < KML::Container
    attr_accessor :geometry  
        
    


  
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Placemark {
        super
        features.each { |f| f.render(xm) }
        plain_children.each { |c| xm << c }
        geometry.render(xm) unless geometry.nil?
       xm.ExtendedData {
       xm.Data {
		
		xm.name ('Informations')
		
		xm.value (("Altitude : #{Point.class_variable_get(:@@coordinates_alt)} pieds") << "\n" << ("Latitude : #{Point.class_variable_get(:@@coordinates_lat)} ") << "\n" << ("Longitude : #{Point.class_variable_get(:@@coordinates_long)} "))
        	 }

	
}

      }

    
    end
    def self.parse(node)
      self.new.parse(node)
    end

    def parse(node)
      super(node) do |cld|
        case cld.name
        when 'MultiGeometry'
          self.geometry = KML::MultiGeometry.parse(cld)
        when 'Polygon'
          self.geometry = KML::Polygon.parse(cld)
        when 'Point'
          self.geometry = KML::Point.parse(cld)
        else
          puts "Placemark"
          p cld
          puts
        end
      end
      self
    end
  end
end
Ce qui donne le résultat suivant (oui, je fais encore voler des framboises ;) )
Image

A noter que le fichier adsb.kml est plutôt long à générer, c'est une bonne idée de changer la réactualisation du fichier dans refresh.kml

Code : Tout sélectionner

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.1">
<Document>
  <NetworkLink>
    <Link>
      <href>http://ip_de_votre_Framboise:4567/adsb.kml</href>
      <refreshMode>onInterval</refreshMode>
      <refreshInterval>15</refreshInterval>
    </Link>
    </NetworkLink>
</Document>
</kml>
Edit :

J'ai légèrement modifié le code pour avoir le résultat suivant :
Image

voici les modif à effectuer :

Dans "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/placement.rb" :

Code : Tout sélectionner


# Basic XML Structure:
#
#   <Placemark id="ID">
#     <!-- inherited from Feature element -->
#     <name>...</name>                      <!-- string -->
#     <visibility>1</visibility>            <!-- boolean -->
#     <open>1</open>                        <!-- boolean -->
#     <address>...</address>                <!-- string -->
#     <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
#         </AddressDetails>                 <!-- string -->
#     <phoneNumber>...</phoneNumber>        <!-- string -->
#     <Snippet maxLines="2">...</Snippet>   <!-- string -->
#     <description>...</description>        <!-- string -->
#     <LookAt>...</LookAt>
#     <TimePrimitive>...</TimePrimitive>
#     <styleUrl>...</styleUrl>              <!-- anyURI -->
#     <StyleSelector>...</StyleSelector>
#     <Region>...</Region>
#     <Metadata>...</Metadata>
#
#     <!-- specific to Placemark element -->
#     <Geometry>...</Geometry>
#   </Placemark>


module KML
  class Placemark < KML::Container
    attr_accessor :geometry  
        
    


  
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Placemark {
        super
        features.each { |f| f.render(xm) }
        plain_children.each { |c| xm << c }
        geometry.render(xm) unless geometry.nil?
       xm.ExtendedData {
       xm.Data(:name => 'altitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_alt))
        	 }
xm.Data(:name => 'latitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_lat))
        	 }
xm.Data(:name => 'longitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_long))
        	 }
xm.Data(:name => 'heading'){	
		
		
		xm.value(IconStyle.class_variable_get(:@@coordinates_heading))
        	 }

xm.Data(:name => 'icao'){	
		
		
		xm.value(name)
        	 }



	
}

      }

    
    end

    def self.parse(node)
      self.new.parse(node)
    end

    def parse(node)
      super(node) do |cld|
        case cld.name
        when 'MultiGeometry'
          self.geometry = KML::MultiGeometry.parse(cld)
        when 'Polygon'
          self.geometry = KML::Polygon.parse(cld)
        when 'Point'
          self.geometry = KML::Point.parse(cld)
        else
          puts "Placemark"
          p cld
          puts
        end
      end
      self
    end
  end
end
Dans "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/style.rb" :

Code : Tout sélectionner

module KML
  # A Style defines an addressable style group that can be referenced by StyleMaps and Features. Styles affect 
  # how Geometry is presented in the 3D viewer and how Features appear in the Places panel of the List view. 
  # Shared styles are collected in a Document and must have an id defined for them so that they can be referenced 
  # by the individual Features that use them.
  class Style < StyleSelector
    attr_accessor :icon_style
    attr_accessor :label_style
    attr_accessor :line_style
    attr_accessor :poly_style
    attr_accessor :balloon_style
    attr_accessor :list_style
    
    
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Style(:id => id) {
        %w(Icon Label Line Poly Balloon List).each do |name| 
          field = "#{name.downcase}_style".to_sym
          self.__send__(field).render(xm) unless self.__send__(field).nil?
        end
	xm.BalloonStyle {
	  xm.text("<p align =center><font size = 5><b>$[icao]</b></font></p> <font size = 4><u>Altitude </u>:  $[altitude] pieds <br/> <u>Latitude </u>:  $[latitude] <br/> <u>Longitude </u>:  $[longitude] <br/> <u>Heading </u>:  $[heading] &deg;</font>" )
	   		
          }
      }
    end
  end
end
Les modifications dans ce code sont plutôt simples.
Toute la balise "xm.text" n'est que de l'HTML
Quant aux varialbe ($[altitude] par exemple), elles sont prises directement dans le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/placement.rb"
Il s'agit du nom donné à la balise xm.data (xm.Data(:name => 'altitude') dans le cas choisis)


Dans "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/icon_style.rb" :

Code : Tout sélectionner

# Source file contains the code for creating the IconStyle element:
#
# <IconStyle id="ID">
#   <!-- inherited from ColorStyle -->
#   <color>ffffffff</color>            <!-- kml:color -->
#   <colorMode>normal</colorMode>      <!-- kml:colorModeEnum:normal or random -->
# 
#   <!-- specific to IconStyle -->
#   <scale>1</scale>                   <!-- float -->
#   <heading>0</heading>               <!-- float -->
#   <Icon>
#     <href>...</href>
#   </Icon> 
#   <hotSpot x="0.5"  y="0.5" 
#     xunits="fraction" yunits="fraction"/>    <!-- kml:vec2Type -->                    
# </IconStyle>

module KML #:nodoc:
  # Specifies how icons for point Placemarks are drawn, both in the Places panel and in the 3D viewer of 
  # Google Earth. The Icon object specifies the icon image. The +scale+ specifies the x, y scaling of the 
  # icon.
  class IconStyle < ColorStyle
    # Compass direction, in degrees. Default=0 (North). (
    # <a href="http://earth.google.com/kml/kml_tags_21.html#heading">See diagram.) Values range from 0 to 
    # ±180 degrees.
    attr_accessor :heading
    def coordinates_heading
      @@coordinates_heading
    end   
    
    # Resizes the icon (default=1).
    attr_accessor :scale
    
    # A custom Icon.
    attr_accessor :icon
    
    # Specifies the position within the Icon that is "anchored" to the Point specified in the Placemark.
    # See KML::HotSpot
    attr_accessor :hot_spot
    
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.IconStyle {
        super
        xm.scale(scale) unless scale.nil?
        xm.heading(heading) unless heading.nil?        	 
	 @@coordinates_heading = (heading) unless heading.nil?
	 		
        icon.render(xm) unless icon.nil?
        unless hot_spot.nil?
          xm.hotSpot(:x => hot_spot.x, :y => hot_spot.y, :xunits => hot_spot.xunits, :yunits => hot_spot.yunits)
        end
      }
    end
  end
end

require 'kml/hot_spot'
Amusez-vous bien :D

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » lun. 11 mai 2015 22:34

J'ai fais quelques modifications :D :
Image Image Image

Malheureusement, c'est pas vraiment publiable :(

1) Ruby me bouffe énormément de ressources sur mon Raspberry 1 B
Le CPU est quasiment à 100% lors de la génération du fichier kml
Faudrait tester sur le 2

2) Le site qui fournit l' API pour récupérer les miniatures, limite le nombre de requêtes.
Vu que j'ai pas mal d'avions en simultanés, le site finit par envoyer une réponse 429 (rate limit), est plus aucune image de dispo pendent un petit moment :(
Faudrait se faire une base de données locale.
Ou alors faudrait indiquer dans le fichier KML de ne télécharger le fichier json contenant l'url de la miniature que lorsqu'on clic sur un avion.
Chose que je ne sais pas faire.

Si il y a un développeur dans le coin....

Sinon, il y a gr-air-modes , qui a une option pour générer automatiquement un fichier kml
Mais pas encore eu le temps de tester. Et idéalement, je préférerai continuer à utiliser Modesdeco2

Avatar du membre
vague nerd
Modérateur
Messages : 1473
Enregistré le : mar. 14 oct. 2014 11:42
Localisation : France !

Re: Récepteur ADS-B sur Raspberry Pi

Message par vague nerd » mer. 13 mai 2015 20:46

Bonjour.

Pourriez-vous nous poster un lien vers votre fichier kml, svp ?

Cdt.
Cordialement,

Vague Nerd

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » ven. 15 mai 2015 12:16

Bonjour,

ICI pour le KML et le fichier pour l'icone de l'avion : ICI (à mettre dans le même dossier que le fichier KML)

Fichier généré par adsb2kml. Pas de parcours malheureusement
A noter que les miniatures ne s'afficheront pas.
J'ai opté pour télécharger localement les miniatures pour éviter d'effectuer sans cesse des requêtes sur airport-data (qui bloque pendent 1h si le nombre de requêtes est trop important)
Les photos étant sous copyright, je préfère éviter de proposer un lien vers l'archive (du moins publiquement)

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » sam. 16 mai 2015 22:46

Salut,

le code pour récupérer et afficher les miniatures fonctionne a peu près bien :)
N'y connaissant rien en programmation (ou presque), ça m'a pris un temps fou :cry:

Donc, le code télécharge maintenant les miniatures localement (via l'API de airport-data)
Et cette portion de code ne s’exécute que toutes les 15 min (si le code status est différent de 429 - ce qui correspond à une limite de requêtes atteinte) ou 30 mins (si le code status est à 429)
Entre, aucune vérification en ligne n'est effectuée, et uniquement les photos dispo localement sont incluses dans le fichier KML.
Ce qui réduit énormément le temps de génération du fichier.

Je préviens mon code est moche et dégueulasse, faudra voir à l'améliorer

Le code maintenant :) :

Faut commencer par installer un serveur web, si vous n'en avez pas :

Code : Tout sélectionner

apt-get install lighttpd
une fois installé, créer un dossier "photo" dans "/var/www"

Installation des gems nécessaires :

Code : Tout sélectionner

gem install json
gem install mechanize
gem install thin
Modification à apporter :

Code : Tout sélectionner

editer le fichier "/var/lib/gems/1.9.1/gems/thin-1.6.3/lib/thin/server.rb :
chercher : DEFAULT_TIMEOUT et mettre la valeur à 240

editer le fichier "/var/lib/gems/1.9.1/gems/sinatra-1.4.6/lib/sinatra/base.rb"
chercher => set :server, %w[HTTP webrick]
et remplacer par => set :server, %w[thin mongrel webrick]
Modification de ruby_kml :

Editer le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/placemark.rb"

Code : Tout sélectionner

require 'rubygems'
require 'json'
require 'net/http'
require 'mechanize' 
require 'pp'

# Basic XML Structure:
#
#   <Placemark id="ID">
#     <!-- inherited from Feature element -->
#     <name>...</name>                      <!-- string -->
#     <visibility>1</visibility>            <!-- boolean -->
#     <open>1</open>                        <!-- boolean -->
#     <address>...</address>                <!-- string -->
#     <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
#         </AddressDetails>                 <!-- string -->
#     <phoneNumber>...</phoneNumber>        <!-- string -->
#     <Snippet maxLines="2">...</Snippet>   <!-- string -->
#     <description>...</description>        <!-- string -->
#     <LookAt>...</LookAt>
#     <TimePrimitive>...</TimePrimitive>
#     <styleUrl>...</styleUrl>              <!-- anyURI -->
#     <StyleSelector>...</StyleSelector>
#     <Region>...</Region>
#     <Metadata>...</Metadata>
#
#     <!-- specific to Placemark element -->
#     <Geometry>...</Geometry>
#   </Placemark>


module KML
  class Placemark < KML::Container
    attr_accessor :geometry  
        
          
    
    def render(xm=Builder::XmlMarkup.new(:indent => 2))       
      xm.Placemark { 		  
        super
        features.each { |f| f.render(xm) }
        plain_children.each { |c| xm << c }
        geometry.render(xm) unless geometry.nil?
        www_image = "/var/www/photo/" << name << ".jpg"
     #   puts @@run_number_read

       
      

 if KMLFile.class_variable_get(:@@number_run) == "0"
 
	status_json1 = File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb')
 
if !File.exist?(www_image) && status_json1 != "429"
	aircraft_url = "http://www.airport-data.com/api/ac_thumb.json?m=" << name
	uri = URI(aircraft_url)
	json = Net::HTTP.get(uri)
	json = JSON.parse(json)	
       puts json["status"]
	File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb', json["status"])
       status_json1 = json["status"]
       
 end

   if  status_json1 == 200  && !File.exist?(www_image)
	# aircraft_photo = json["data"][0]["image"]
       agent = Mechanize.new
       agent.get(json["data"][0]["image"]).save www_image

    end 
	
end


if File.exist?(www_image)
    aircraft_photo1 = ("http://192.168.0.109/photo/" << name << ".jpg" )
else     
    aircraft_photo1 = ("http://192.168.0.109/photo/aircraft.jpg")
end

       xm.ExtendedData {
       xm.Data(:name => 'altitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_alt))
        	 }
xm.Data(:name => 'latitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_lat))
        	 }
xm.Data(:name => 'longitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_long))
        	 }
xm.Data(:name => 'heading'){	
		
		
		xm.value(IconStyle.class_variable_get(:@@coordinates_heading))
        	 }

xm.Data(:name => 'callsign'){	
		
		
		xm.value(name)
        	 }

xm.Data(:name => 'photo'){	
		
		
		xm.value(aircraft_photo1)
        	 }




	
}

      }
   

    end

  

    def self.parse(node)

      self.new.parse(node)
  #  File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb', "1")
    end

    def parse(node)
      super(node) do |cld|      
        case cld.name
        when 'MultiGeometry'
          self.geometry = KML::MultiGeometry.parse(cld)
        when 'Polygon'
          self.geometry = KML::Polygon.parse(cld)
        when 'Point'
          self.geometry = KML::Point.parse(cld)
        else
          puts "Placemark"
          p cld
          puts        
        end     
      end     
      self
    end
  end 
end
Attention à ces 2 lignes :

Code : Tout sélectionner

aircraft_photo1 = ("http://192.168.0.109/photo/" << name << ".jpg" )
else     
    aircraft_photo1 = ("http://192.168.0.109/photo/aircraft.jpg")
Faut remplacer l'adresse IP par celle de votre raspberry
et inclure un fichier "aircraft.jpg" dans "/var/www/photo"
Il s'agit de l'image utilisée par défaut quand aucune miniature n'est dispo

Éditer le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/style.rb"

Code : Tout sélectionner

module KML
  # A Style defines an addressable style group that can be referenced by StyleMaps and Features. Styles affect 
  # how Geometry is presented in the 3D viewer and how Features appear in the Places panel of the List view. 
  # Shared styles are collected in a Document and must have an id defined for them so that they can be referenced 
  # by the individual Features that use them.
  class Style < StyleSelector
    attr_accessor :icon_style
    attr_accessor :label_style
    attr_accessor :line_style
    attr_accessor :poly_style
    attr_accessor :balloon_style
    attr_accessor :list_style
    
    
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Style(:id => id) {
        %w(Icon Label Line Poly Balloon List).each do |name| 
          field = "#{name.downcase}_style".to_sym
          self.__send__(field).render(xm) unless self.__send__(field).nil?
        end
	xm.BalloonStyle {
	  xm.text("<body>
		<p style=\"text-align: center;\">
			<span style=\"font-size:26px;\"><strong>$[callsign]</strong></span></p>
		<table align=\"center\" border=\"0\" cellpadding=\"1\" cellspacing=\"1\" height=\"135\" width=\"280\">
			<tbody>
				<tr>
					<td>
						<u><span style=\"font-size:22px;\">Altitude :</span></u></td>
					<td style=\"text-align: justify;\">
						<span style=\"font-size:22px;\">$[altitude] pieds</span></td>
				</tr>
				<tr>
					<td>
						<u><span style=\"font-size:22px;\">Latitude :</span></u></td>
					<td style=\"text-align: justify;\">
						<span style=\"font-size:22px;\">$[latitude]&deg;</span></td>
				</tr>
				<tr>
					<td>
						<u><span style=\"font-size:22px;\">Longitude :</span></u></td>
					<td style=\"text-align: justify;\">
						<span style=\"font-size:22px;\">$[longitude]&deg;</span></td>
				</tr>
				<tr>
					<td>
						<u><span style=\"font-size:22px;\">Heading :</span></u></td>
					<td style=\"text-align: justify;\">
						<span style=\"font-size:22px;\">$[heading]&deg;</span></td>
				</tr>
			</tbody>
		</table>
		<p style=\"text-align: center;\">
			<img alt=\"\" src=\"$[photo]\" /></p>
	</body>")}
      }
    end
  end
end
Editer le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/icon_style.rb"

Code : Tout sélectionner

# Source file contains the code for creating the IconStyle element:
#
# <IconStyle id="ID">
#   <!-- inherited from ColorStyle -->
#   <color>ffffffff</color>            <!-- kml:color -->
#   <colorMode>normal</colorMode>      <!-- kml:colorModeEnum:normal or random -->
# 
#   <!-- specific to IconStyle -->
#   <scale>1</scale>                   <!-- float -->
#   <heading>0</heading>               <!-- float -->
#   <Icon>
#     <href>...</href>
#   </Icon> 
#   <hotSpot x="0.5"  y="0.5" 
#     xunits="fraction" yunits="fraction"/>    <!-- kml:vec2Type -->                    
# </IconStyle>

module KML #:nodoc:
  # Specifies how icons for point Placemarks are drawn, both in the Places panel and in the 3D viewer of 
  # Google Earth. The Icon object specifies the icon image. The +scale+ specifies the x, y scaling of the 
  # icon.
  class IconStyle < ColorStyle
    # Compass direction, in degrees. Default=0 (North). (
    # <a href="http://earth.google.com/kml/kml_tags_21.html#heading">See diagram.) Values range from 0 to 
    # ±180 degrees.
    attr_accessor :heading
    def coordinates_heading
      @@coordinates_heading
    end   
    
    # Resizes the icon (default=1).
    attr_accessor :scale
    
    # A custom Icon.
    attr_accessor :icon
    
    # Specifies the position within the Icon that is "anchored" to the Point specified in the Placemark.
    # See KML::HotSpot
    attr_accessor :hot_spot
    
    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.IconStyle {
        super
        xm.scale(scale) unless scale.nil?
        xm.heading(heading) unless heading.nil?        	 
	 @@coordinates_heading = (heading) unless heading.nil?
	 		
        icon.render(xm) unless icon.nil?
        unless hot_spot.nil?
          xm.hotSpot(:x => hot_spot.x, :y => hot_spot.y, :xunits => hot_spot.xunits, :yunits => hot_spot.yunits)
        end
      }
    end
  end
end

require 'kml/hot_spot'
Editer le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/point.rb"

Code : Tout sélectionner

# <Point id="ID">
#   <!-- specific to Point -->
#   <extrude>0</extrude>                   <!-- boolean -->
#   <tessellate>0</tessellate>             <!-- boolean -->
#   <altitudeMode>absolute</altitudeMode> 
#     <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
#   <coordinates>...</coordinates>         <!-- lon,lat[,alt] -->
# </Point>
module KML
  class Point < Geometry

    # A single tuple consisting of floating point values for longitude, latitude, and altitude (in that order). 
    # Longitude and latitude values are in degrees, where:
    #
    # * longitude >= -180 and <= 180
    # * latitude >= -90 and <= 90
    # * altitude values (optional) are in meters above sea level
    
     def coordinates
      @coordinates
    end
     attr_accessor :coordinates

def coordinates_alt
      @@coordinates_alt
    end   

def coordinates_lat
      @@coordinates_lat
    end    

def coordinates_long
      @@coordinates_long
    end      
     


    # Set the coordinates
    def coordinates=(c)
      case c
      when String
        @coordinates = c.strip.split(',')
        unless @coordinates.length == 2 || @coordinates.length == 3
          raise "Coordinates string may only have 2 parts (indicating lat and long) or 3 parts (lat, long and altitude)"
        end
      when Array
        @coordinates = c
      when Hash
        @coordinates = [:lng, :lat, :alt].collect {|attr| c[attr]}.compact
	 
      else
        raise ArgumentError, "Coordinates must be either a String, Hash or an Array"
      end
	
    end
      

    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.Point {
        super
        xm.coordinates(coordinates.join(","))
        @@coordinates_alt = (coordinates[2]) 
        @@coordinates_lat = (coordinates[1]) 
        @@coordinates_long = (coordinates[0])    

      }
    end

    def self.parse(node)
      self.new.parse(node)
    end
       

    def parse(node)
      super(node) do |cld|
        case cld.name
        when 'coordinates'
          self.coordinates = cld.content
        else
          puts "Point"
          p cld
          puts
        end
      end
      self
    end

  end
end
Editer "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/geometry.rb"

Code : Tout sélectionner

module KML
  class Geometry < KML::Container
    # Specifies whether to connect the point to the ground. Extrusion requires that the point's +altitude_mode+ be 
    # either "relativeToGround" or "absolute" and that within the +coordinates+, the altitude component be greater 
    # than 0 (that is, in the air). Default is false.
    def extrude?
      @extrude
    end

    # Set to true to extrude.
    def extrude=(v)
      @extrude = v
    end

    # Return nil if extrude has not been defined, otherwise return '1' for true or '0' for false.
    def extrude
      return nil unless @extrude
      @extrude ? '1' : '0'
    end

    # Specifies whether to allow lines and paths to follow the terrain. This specification applies only to LineStrings 
    # (paths) and LinearRings (polygons) that have an +altitude_mode+ of "clampToGround". Very long lines should enable 
    # tessellation so that they follow the curvature of the earth (otherwise, they may go underground and be hidden).
    # Default is false.
    def tessellate?
      @tessellate
    end

    # Set to true to tessellate.
    def tessellate=(v)
      @tessellate = v
    end

    # Return nil if tessellate has not been defined, otherwise return '1' for true or '0' for false.
    def tessellate
      return nil unless @tessellate
      @tessellate ? '1' : '0'
    end

    # Specifies how altitude components in the <coordinates> element are interpreted. Possible values are:
    # 
    # * clampToGround - (default) Indicates to ignore an altitude specification (for example, in the +coordinates+).
    # * relativeToGround - Sets the altitude of the element relative to the actual ground elevation of a particular 
    #   location. For example, if the ground elevation of a location is exactly at sea level and the altitude for a 
    #   point is set to 9 meters, then the elevation for the icon of a point placemark elevation is 9 meters with 
    #   this mode. However, if the same coordinate is set over a location where the ground elevation is 10 meters 
    #   above sea level, then the elevation of the coordinate is 19 meters. A typical use of this mode is for placing 
    #   telephone poles or a ski lift.
    # * absolute - Sets the altitude of the coordinate relative to sea level, regardless of the actual elevation 
    #   of the terrain beneath the element. For example, if you set the altitude of a coordinate to 10 meters with 
    #   an absolute altitude mode, the icon of a point placemark will appear to be at ground level if the terrain 
    #   beneath is also 10 meters above sea level. If the terrain is 3 meters above sea level, the placemark will 
    #   appear elevated above the terrain by 7 meters. A typical use of this mode is for aircraft placement.
    def altitude_mode
      @altitude_mode = 'absolute'
    end

    def altitude_mode_set?
      !(@altitude_mode.nil?)
    end

    # Set the altitude mode
    def altitude_mode=(mode)
      allowed_modes = %w(clampToGround relativeToGround absolute)
      if allowed_modes.include?(mode)
        @altitude_mode = mode
      else
        raise ArgumentError, "Must be one of the allowed altitude modes: #{allowed_modes.join(',')}"
      end
    end

    def render(xm=Builder::XmlMarkup.new(:indent => 2))
      xm.extrude('1') 
      xm.tessellate('1') 
      xm.altitudeMode ('absolute')
    end

    def self.parse(node)
      self.new.parse(node)
    end

    def parse(node)
      super(node) do |cld|
        case cld.name
        when 'tessellate'
          self.tessellate = cld.content
        else
          yield cld
        end
      end
      self
    end

  end
end

require 'kml/point'
require 'kml/line_string'
require 'kml/linear_ring'
require 'kml/polygon'
require 'kml/model'
require 'kml/multi_geometry'
Editer le fichier "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml_file.rb"

Code : Tout sélectionner

# The KMLFile class is the top level class for constructing KML files. To create a new KML file
# create a KMLFile instance and add KML objects to its objects. For example:
#
#   f = KMLFile.new
#   f.objects << Placemark.new(
#     :name => 'Simple placemark',
#     :description => 'Attached to the ground. Intelligently places itself at the height of the underlying terrain.',
#     :geometry => Point.new(:coordinates=>'-122.0822035425683,37.42228990140251,0')
#   )
#   puts f.render
class KMLFile
  # The objects in the KML file
  def objects
    @objects ||= []
  end
  alias :features :objects

def status_json
      @@status_json
    end

@@status_json = File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb')
puts @@status_json

def number_run
      @@number_run
    end

@@number_run = File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb')
puts @@number_run
  # Render the KML file
  def render(xm=Builder::XmlMarkup.new(:indent => 2))



    xm.instruct!    
    xm.kml(:xmlns => 'http://earth.google.com/kml/2.1'){
      xm.altitudeMode ('absolute')
      objects.each { |o| o.render(xm) } 


      if  File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb') == "0"

    File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb', "1")
  
    end

  if File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb') == "1"  
     time_run1 = Time.now
     puts time_run1

     if  File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb') == "429"
       wait_time = 1800
       print "30 minutes"
     else
       wait_time = 900
	print "15 minutes"
     end

    File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb', "2")
    time_run1 = (time_run1 + wait_time)
    File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_time.rb', time_run1)
  end
     
          
  if Time.now.to_s > File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_time.rb')
     File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb', "0")
     File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_time.rb', "0")
     File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb', "0")
  end 

 @@status_json = File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/json.rb')
@@number_run = File.read('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb')   
   
    }

  
  end

  def save filename
    File.open(filename, 'w') { |f| f.write render }
  end

  # Parse the KML file using nokogiri
  # <kml xmlns="http://www.opengis.net/kml/2.2">
  #   <NetworkLinkControl> ... </NetworkLinkControl>
  #   <!-- 0 or 1 Feature elements -->
  # </kml>
  def self.parse(io)
    kml = self.new
    doc = Nokogiri::XML::Document.parse(io)
    doc.root.element_children.each do |cld|
      case cld.name
      when 'Document'
        kml.features << KML::Document.parse(cld)
      when 'Folder'
      when 'NetworkLink'
      when 'Placemark'
      when 'GroundOverlay'
      when 'PhotoOverlay'
      when 'ScreenOverlay'
      end
    end
    kml
  end

end

require 'kml/object'
Et faut créer 3 fichiers vides (ou à 0) : run_time.rb / run_number.rb / json.rb dans "/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml"

Et ensuite lancer adsb2kml via la commande :

Code : Tout sélectionner

cd adsb2kml  (si vous n'êtes pas déjà dans le dossier)
ruby sin_fe.rb
Je pense n'avoir rien oublié.
Et avec un peu de chance ça devrait fonctionner.
C'est à dire que à chaque fois que je corrige un bug, j'en créer de nouveaux au passages :( :x :cry:

Edit :

Petites modifications dans Placemark.rb et kml_file.rb, de manière à utiliser YAML et avoir 1 seul fichier de config au lieu de 3 comme auparavant

placemark.rb :

Code : Tout sélectionner

require 'rubygems'
require 'json'
require 'net/http'
require 'mechanize' 
require 'pp'
require 'yaml'

# Basic XML Structure:
#
#   <Placemark id="ID">
#     <!-- inherited from Feature element -->
#     <name>...</name>                      <!-- string -->
#     <visibility>1</visibility>            <!-- boolean -->
#     <open>1</open>                        <!-- boolean -->
#     <address>...</address>                <!-- string -->
#     <AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">...
#         </AddressDetails>                 <!-- string -->
#     <phoneNumber>...</phoneNumber>        <!-- string -->
#     <Snippet maxLines="2">...</Snippet>   <!-- string -->
#     <description>...</description>        <!-- string -->
#     <LookAt>...</LookAt>
#     <TimePrimitive>...</TimePrimitive>
#     <styleUrl>...</styleUrl>              <!-- anyURI -->
#     <StyleSelector>...</StyleSelector>
#     <Region>...</Region>
#     <Metadata>...</Metadata>
#
#     <!-- specific to Placemark element -->
#     <Geometry>...</Geometry>
#   </Placemark>


module KML
  class Placemark < KML::Container
    attr_accessor :geometry
  
  
    def render(xm=Builder::XmlMarkup.new(:indent => 2))       
      xm.Placemark { 		  
        super
        features.each { |f| f.render(xm) }
        plain_children.each { |c| xm << c }
        geometry.render(xm) unless geometry.nil?
        www_image = "/var/www/photo/" << name << ".jpg"
     #   puts @@run_number_read

       
    #  data1 = YAML.load_file "/root/ruby/essais.yml"

 if KMLFile.class_variable_get(:@@number_run) == 0
 
    status_json1 = KMLFile.class_variable_get(:@@status_json)
 
if !File.exist?(www_image) && status_json1 != 429
	aircraft_url = "http://www.airport-data.com/api/ac_thumb.json?m=" << name
	uri = URI(aircraft_url)
	json = Net::HTTP.get(uri)
	json = JSON.parse(json)	
       puts json["status"]
	@@status_json = json["status"]    
                 

   if  json["status"] == 200	
       agent = Mechanize.new
       agent.get(json["data"][0]["image"]).save www_image

    end 
	
end
end

if File.exist?(www_image)
    aircraft_photo1 = ("http://192.168.0.109/photo/" << name << ".jpg" )
else     
    aircraft_photo1 = ("http://192.168.0.109/photo/aircraft.jpg")
end

       xm.ExtendedData {
       xm.Data(:name => 'altitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_alt))
        	 }
xm.Data(:name => 'latitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_lat))
        	 }
xm.Data(:name => 'longitude'){	
		
		
		xm.value(Point.class_variable_get(:@@coordinates_long))
        	 }
xm.Data(:name => 'heading'){	
		
		
		xm.value(IconStyle.class_variable_get(:@@coordinates_heading))
        	 }

xm.Data(:name => 'callsign'){	
		
		
		xm.value(name)
        	 }

xm.Data(:name => 'photo'){	
		
		
		xm.value(aircraft_photo1)
        	 }




	
}

      }
   

    end

  

    def self.parse(node)

      self.new.parse(node)
  #  File.write('/var/lib/gems/1.9.1/gems/ruby_kml-0.1.7/lib/kml/run_number.rb', "1")
    end

    def parse(node)
      super(node) do |cld|      
        case cld.name
        when 'MultiGeometry'
          self.geometry = KML::MultiGeometry.parse(cld)
        when 'Polygon'
          self.geometry = KML::Polygon.parse(cld)
        when 'Point'
          self.geometry = KML::Point.parse(cld)
        else
          puts "Placemark"
          p cld
          puts        
        end     
      end     
      self
    end
  end 
end
et kml_file.rb :

Code : Tout sélectionner

# The KMLFile class is the top level class for constructing KML files. To create a new KML file
# create a KMLFile instance and add KML objects to its objects. For example:
#
#   f = KMLFile.new
#   f.objects << Placemark.new(
#     :name => 'Simple placemark',
#     :description => 'Attached to the ground. Intelligently places itself at the height of the underlying terrain.',
#     :geometry => Point.new(:coordinates=>'-122.0822035425683,37.42228990140251,0')
#   )
#   puts f.render
require 'yaml'

class KMLFile
  # The objects in the KML file
  def objects
    @objects ||= []
  end
  alias :features :objects

data = YAML.load_file "/root/ruby/essais.yml"

def status_json
      @@status_json
    end

@@status_json = data["Json"]
puts @@status_json

def run_time
      @@run_time
    end

@@run_time = data["Time"]
puts @@run_time


def number_run
      @@number_run
    end

@@number_run = data["Run"]
puts @@number_run

  # Render the KML file
  def render(xm=Builder::XmlMarkup.new(:indent => 2))



    xm.instruct!    
    xm.kml(:xmlns => 'http://earth.google.com/kml/2.1'){
      xm.altitudeMode ('absolute')
      objects.each { |o| o.render(xm) } 

     data = YAML.load_file "/root/ruby/essais.yml"

  
      if  data["Run"] == 0

     data["Run"] = 1
  
    end

  
  if data["Run"] == 1  
     time_run1 = Time.now
     puts time_run1

     if  @@status_json == 429
       wait_time = 1800
       print "30 minutes"
     else
       wait_time = 900
	print "15 minutes"
     end

     data["Run"] = 2     
     time_run1 = (time_run1 + wait_time)
     data["Time"] = time_run1   
     data["Json"] = @@status_json  
      
  end     
          
  if Time.now.to_s > data["Time"].to_s
     data["Run"] = 0
     data["Time"] = "0"
     data["Json"] = 0
     # @@essais = 0
     
       end 
 
   File.open("/root/ruby/essais.yml", 'w') { |f| YAML.dump(data, f) }
       sleep 2
   data = YAML.load_file "/root/ruby/essais.yml"
   @@number_run = data["Run"]
   @@status_json = data["Json"]
   @@run_time = data["Time"] 
       
    }

  
  end

  def save filename
    File.open(filename, 'w') { |f| f.write render }
  end

  # Parse the KML file using nokogiri
  # <kml xmlns="http://www.opengis.net/kml/2.2">
  #   <NetworkLinkControl> ... </NetworkLinkControl>
  #   <!-- 0 or 1 Feature elements -->
  # </kml>
  def self.parse(io)
    kml = self.new
    doc = Nokogiri::XML::Document.parse(io)
    doc.root.element_children.each do |cld|
      case cld.name
      when 'Document'
        kml.features << KML::Document.parse(cld)
      when 'Folder'
      when 'NetworkLink'
      when 'Placemark'
      when 'GroundOverlay'
      when 'PhotoOverlay'
      when 'ScreenOverlay'
      end
    end
    kml
  end

end

require 'kml/object'
Faut changer dans le code ""/root/ruby/essais.yml"" par le chemin d'accès de votre fichier yml.
Ce fichier devant contenir les lignes suivantes :

Code : Tout sélectionner

---
Run: 0
Time: '0'
Json: 0
Voilà :)

Sinon, attention à adsb2kml.
Perso, après plusieures heures, il me fait tomber le raspberry et fout la merde avec modesmixer2 / modesdeco2
J'ai été obliger de mettre une tâche cron pour redémarrer le tout au moins toutes les 2h

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » ven. 22 mai 2015 15:56

salut,

j'ai reçu cette antenne aujourd'hui : ICI
ImageImage

J'en ai eu pour 32 euros en tout. Ce qui est raisonnable.
A noter que le support pour le mât sert également de protection pour le connecteur de l'antenne. Ce qui est vraiment appréciable.
C'est d'ailleurs la seule antenne que j'ai eu entre les mains qui propose cette protection. D'habitude le connecteur est non protégé, à vous de vous démerder.

Sinon, côté résultats, j'ai testé vite fait en la comparant avec celle de base que j'ai :
Image

En mettant l'antenne sur le volet (antenne d'origine à gauche, celle ebay à droite) :
Image Image

En mettant l'antenne sur la terrasse, sur un mât de 2m (antenne d'origine à gauche, celle ebay à droite) :
Image Image

Le vendeur propose également une version moins chère : ICI
Elle est à priori moins puissante, mais pas testé

J'ai également reçu cette antenne, pour la bande aérienne + NOAA : ICI
Les résultats sont nettement meilleurs qu'avant. Par contre j'ai pas mal de parasites par moment. Je vais voir pour me prendre un filtre

Avatar du membre
brandt71
Messages : 28
Enregistré le : mer. 17 sept. 2014 20:09
Localisation : Clermont-Ferrand

Re: Récepteur ADS-B sur Raspberry Pi

Message par brandt71 » ven. 22 mai 2015 16:18

sawaguna a écrit :salut,

j'ai reçu cette antenne aujourd'hui : ICI
ImageImage

J'en ai eu pour 32 euros en tout. Ce qui est raisonnable.
A noter que le support pour le mât sert également de protection pour le connecteur de l'antenne. Ce qui est vraiment appréciable.
C'est d'ailleurs la seule antenne que j'ai eu entre les mains qui propose cette protection. D'habitude le connecteur est non protégé, à vous de vous démerder.

Sinon, côté résultats, j'ai testé vite fait en la comparant avec celle de base que j'ai :
Image

En mettant l'antenne sur le volet (antenne d'origine à gauche, celle ebay à droite) :
Image Image

En mettant l'antenne sur la terrasse, sur un mât de 2m (antenne d'origine à gauche, celle ebay à droite) :
Image Image

Le vendeur propose également une version moins chère : ICI
Elle est à priori moins puissante, mais pas testé

J'ai également reçu cette antenne, pour la bande aérienne + NOAA : ICI
Les résultats sont nettement meilleurs qu'avant. Par contre j'ai pas mal de parasites par moment. Je vais voir pour me prendre un filtre
Très net progression de la couverture, c'est impressionnant ! Je suis maintenant convaincu qu'il faut que j’achète ce genre d'antenne, malgré ma mauvaise implantation je devrais avoir un gain important.

sawaguna
Messages : 34
Enregistré le : lun. 27 avr. 2015 13:55

Re: Récepteur ADS-B sur Raspberry Pi

Message par sawaguna » ven. 22 mai 2015 16:53

t'as pu tester l'antenne que tu souhaitais te fabriquer finalement ?

Y a un topic intéressant sur planefinder concernant les design "maison", ICI
Mais c'est chaud à suivre, le topic étant quand même bien technique
Le design "spider" a l'air de donner de bons résultats.

Sinon, toujours sur l'antenne ebay, en comparaison de celle de base.
Un petit test dans des conditions affreuses : à l'intérieure, derrière une vitre (volets ouverts) :
Image Image

Au passage, les soucis de fuites de mémoire de Modesdeco2 semblent être totalement corrigés. ça fait plus d'une semaine maitenant que je n'ai plus de probèmes, et ce sans devoir redémarrer le logiciel via une tache cron :)

Répondre

Retourner vers « Et tout le reste »