Ejemplo n.º 1
0
    def run(self):
        """Run the flight tracker.
        """
        logging.info("Connecting to MQTT broker on %s:%s" % (self.__mqtt_broker, self.__mqtt_port))
        self.__mqtt_bridge = mqtt_wrapper.bridge(host = self.__mqtt_broker, port = self.__mqtt_port, client_id = "FlightTracker-%d" % (os.getpid())) # TOOD: , user_id = args.mqtt_user, password = args.mqtt_password)
        threading.Thread(target = self.__publish_thread, daemon = True).start()

        while True:
            if not self.dump1090Connect():
                continue
            for data in self.dump1090Read():
                if data is None:
                    continue
                self.cleanObservations()
                m = sbs1.parse(data)
                if m:
                    icao24 = m["icao24"]
                    if icao24 in self.__observations:
                        self.__observations[icao24].update(m)
                    else:
                        self.__observations[icao24] = Observation(m)

                    if self.__observations[icao24].isPresentable():
                        if not self.__tracking_icao24:
                            self.__tracking_icao24 = icao24
                            self.updateTrackingDistance()
                            logging.info("Tracking %s at %d" % (self.__tracking_icao24, self.__tracking_distance))
                        elif self.__tracking_icao24 == icao24:
                            self.updateTrackingDistance()
                        else:
                            distance = utils.coordinate_distance(self.__latitude, self.__longitude, self.__observations[icao24].getLat(), self.__observations[icao24].getLon())
                            if distance < self.__tracking_distance:
                                self.__tracking_icao24 = icao24
                                self.__tracking_distance = distance
                                logging.info("Now tracking %s at %d" % (self.__tracking_icao24, self.__tracking_distance))
Ejemplo n.º 2
0
 def __getObservationJson(self, observation):
     (lat, lon, alt) = utils.calc_travel_3d(observation.getLat(),
                                            observation.getLon(),
                                            observation.getAltitude(),
                                            observation.getLatLonTime(),
                                            observation.getAltitudeTime(),
                                            observation.getGroundSpeed(),
                                            observation.getTrack(),
                                            observation.getVerticalRate(),
                                            camera_lead)
     distance3d = utils.coordinate_distance_3d(camera_latitude,
                                               camera_longitude,
                                               camera_altitude, lat, lon,
                                               alt)
     #(latorig, lonorig) = utils.calc_travel(observation.getLat(), observation.getLon(), observation.getLatLonTime(),  observation.getGroundSpeed(), observation.getTrack(), camera_lead)
     distance2d = utils.coordinate_distance(camera_latitude,
                                            camera_longitude, lat, lon)
     bearing = utils.bearingFromCoordinate(
         cameraPosition=[camera_latitude, camera_longitude],
         airplanePosition=[lat, lon],
         heading=observation.getTrack())
     elevation = utils.elevation(distance2d,
                                 cameraAltitude=camera_altitude,
                                 airplaneAltitude=alt)
     cameraTilt = elevation
     cameraPan = utils.cameraPanFromCoordinate(
         cameraPosition=[camera_latitude, camera_longitude],
         airplanePosition=[lat, lon])
     #elevationorig = utils.elevation(distance2d, observation.getAltitude(), camera_altitude)
     return observation.json()
Ejemplo n.º 3
0
    def __publish_thread(self):
        """
        MQTT publish closest observation every second, more often if the plane is closer
        """
        while True:
            if not self.__tracking_icao24:
                time.sleep(1)
            else:
                if not self.__tracking_icao24 in self.__observations:
                    self.__tracking_icao24 is None
                    continue
                cur = self.__observations[self.__tracking_icao24]
                if cur is None:
                    continue
                (lat, lon) = utils.calc_travel(cur.getLat(), cur.getLon(), cur.getLoggedDate(), cur.getGroundSpeed(), cur.getHeading())
                distance = utils.coordinate_distance(self.__latitude, self.__longitude, lat, lon)
                # Round off to nearest 100 meters
                distance = round(distance/100) * 100
                bearing = utils.bearing(self.__latitude, self.__longitude, lat, lon)

                # @todo: update altitude
                # altitude = sbs1["altitude"]

                retain = False
                self.__mqtt_bridge.publish(self.__prox_topic, cur.json(bearing, distance), 0, retain)
                logging.info("%s at %5d brg %3d alt %5d trk %3d spd %3d %s" % (cur.getIcao24(), distance, bearing, cur.getAltitude(), cur.getHeading(), cur.getGroundSpeed(), cur.getType()))

                if distance < 3000:
                    time.sleep(0.25)
                elif distance < 6000:
                    time.sleep(0.5)
                else:
                    time.sleep(1)
Ejemplo n.º 4
0
    def run(self):
        """Run the flight tracker.
        """
        print("connecting to MQTT broker at " + self.__mqtt_broker +
              ", subcribing on channel '" + self.__plane_topic +
              "'publising on: " + self.__tracking_topic)
        self.__client = mqtt.Client("skyscan-tracker-" +
                                    ID)  #create new instance

        self.__client.on_message = on_message  #attach function to callback
        print("setup MQTT")
        self.__client.connect(self.__mqtt_broker)  #connect to broker
        print("connected mqtt")
        self.__client.loop_start()  #start the loop
        print("start MQTT")
        self.__client.subscribe(self.__plane_topic)
        self.__client.subscribe("skyscan/egi")
        self.__client.publish("skyscan/registration",
                              "skyscan-tracker-" + ID + " Registration", 0,
                              False)
        print("subscribe mqtt")
        threading.Thread(target=self.__publish_thread, daemon=True).start()

        while True:
            while not q.empty():
                m = q.get()
                icao24 = m["icao24"]
                self.cleanObservations()
                if icao24 not in self.__observations:
                    self.__observations[icao24] = Observation(m)
                self.__observations[icao24].update(m)
                if self.__observations[icao24].isPresentable():
                    if not self.__tracking_icao24:
                        if self.__observations[icao24].getElevation(
                        ) != None and self.__observations[icao24].getElevation(
                        ) > min_elevation:
                            self.__tracking_icao24 = icao24
                            self.updateTrackingDistance()
                            logging.info(
                                "Tracking %s at %d elevation: %d" %
                                (self.__tracking_icao24,
                                 self.__tracking_distance,
                                 self.__observations[icao24].getElevation()))
                    elif self.__tracking_icao24 == icao24:
                        self.updateTrackingDistance()
                    else:
                        distance = utils.coordinate_distance(
                            camera_latitude, camera_longitude,
                            self.__observations[icao24].getLat(),
                            self.__observations[icao24].getLon())
                        if distance < self.__tracking_distance and self.__observations[
                                icao24].getElevation() > min_elevation:
                            self.__tracking_icao24 = icao24
                            self.__tracking_distance = distance
                            logging.info(
                                "Tracking %s at %d elevation: %d" %
                                (self.__tracking_icao24,
                                 self.__tracking_distance,
                                 self.__observations[icao24].getElevation()))
            time.sleep(0.1)
Ejemplo n.º 5
0
def calculateCameraPosition():
    global cameraPan
    global cameraTilt
    global distance2d
    global distance3d
    global bearing
    global angularVelocityHorizontal
    global angularVelocityVertical
    global elevation

    (lat, lon, alt) = utils.calc_travel_3d(currentPlane, camera_lead)
    distance3d = utils.coordinate_distance_3d(camera_latitude,
                                              camera_longitude,
                                              camera_altitude, lat, lon, alt)
    #(latorig, lonorig) = utils.calc_travel(observation.getLat(), observation.getLon(), observation.getLatLonTime(),  observation.getGroundSpeed(), observation.getTrack(), camera_lead)
    distance2d = utils.coordinate_distance(camera_latitude, camera_longitude,
                                           lat, lon)
    bearing = utils.bearingFromCoordinate(
        cameraPosition=[camera_latitude, camera_longitude],
        airplanePosition=[lat, lon],
        heading=currentPlane["track"])
    elevation = utils.elevation(distance2d,
                                cameraAltitude=camera_altitude,
                                airplaneAltitude=alt)
    (angularVelocityHorizontal,
     angularVelocityVertical) = utils.angular_velocity(currentPlane,
                                                       camera_latitude,
                                                       camera_longitude,
                                                       camera_altitude)
    #logging.info("Angular Velocity - Horizontal: {} Vertical: {}".format(angularVelocityHorizontal, angularVelocityVertical))
    cameraTilt = elevation
    cameraPan = utils.cameraPanFromCoordinate(
        cameraPosition=[camera_latitude, camera_longitude],
        airplanePosition=[lat, lon])
    cameraPan = calculate_bearing_correction(cameraPan)
Ejemplo n.º 6
0
def test_coordinate_distance():
    """Unit test for coordinate_distance()."""
    # Used this app to calculate distance: https://www.movable-type.co.uk/scripts/latlong.html
    lat1, long1 = 39.099912, -94.581213
    lat2, long2 = 38.627089, -90.200203
    expected_distance = 382900.05037560174
    assert coordinate_distance(lat1, long1, lat2, long2) == expected_distance
Ejemplo n.º 7
0
    def update(self, sbs1msg):
        oldData = dict(self.__dict__)
        #self.__loggedDate = datetime.utcnow()
        if sbs1msg["icao24"]:
            self.__icao24 = sbs1msg["icao24"]
        if sbs1msg["callsign"] and self.__callsign != sbs1msg["callsign"]:
            self.__callsign = sbs1msg["callsign"].rstrip()
        if sbs1msg["altitude"]:
            self.__altitude = sbs1msg["altitude"]
            self.__altitudeTime = datetime.utcnow()
        if sbs1msg["groundSpeed"]:
            self.__groundSpeed = sbs1msg["groundSpeed"]
        if sbs1msg["track"]:
            self.__track = sbs1msg["track"]
        if sbs1msg["lat"]:
            self.__lat = sbs1msg["lat"]
            self.__latLonTime = datetime.utcnow()
        if sbs1msg["lon"]:
            self.__lon = sbs1msg["lon"]
            self.__latLonTime = datetime.utcnow()
        if sbs1msg["verticalRate"]:
            self.__verticalRate = sbs1msg["verticalRate"]
        if not self.__verticalRate:
            self.__verticalRate = 0
        if sbs1msg["loggedDate"]:
            self.__loggedDate = datetime.strptime(sbs1msg["loggedDate"],
                                                  '%Y-%m-%d %H:%M:%S.%f')
        if sbs1msg["registration"]:
            self.__registration = sbs1msg["registration"]
        if sbs1msg["manufacturer"]:
            self.__manufacturer = sbs1msg["manufacturer"]
        if sbs1msg["model"]:
            self.__model = sbs1msg["model"]
        if sbs1msg["operator"]:
            self.__operator = sbs1msg["operator"]
        if sbs1msg["type"]:
            self.__type = sbs1msg["type"]

        # Calculates the distance from the cameras location to the airplane. The output is in METERS!
        distance = utils.coordinate_distance(camera_latitude, camera_longitude,
                                             self.__lat, self.__lon)
        #Not sure we want to... commented out for now -> Round off to nearest 100 meters
        self.__distance = distance = distance  #round(distance/100) * 100
        self.__bearing = utils.bearing(camera_latitude, camera_longitude,
                                       self.__lat, self.__lon)
        self.__elevation = utils.elevation(
            distance, self.__altitude,
            camera_altitude)  # Distance and Altitude are both in meters

        # Check if observation was updated
        newData = dict(self.__dict__)
        #del oldData["_Observation__loggedDate"]
        #del newData["_Observation__loggedDate"]
        d = DictDiffer(oldData, newData)
        self.__updated = len(d.changed()) > 0
Ejemplo n.º 8
0
    def __publish_thread(self):
        """
        MQTT publish closest observation every second, more often if the plane is closer
        """
        timeHeartbeat = 0
        while True:
            if timeHeartbeat < time.mktime(time.gmtime()):
                timeHeartbeat = time.mktime(time.gmtime()) + 10
                self.__client.publish("skyscan/heartbeat",
                                      "skyscan-tracker-" + ID + " Heartbeat",
                                      0, False)
            if not self.__tracking_icao24:
                time.sleep(1)
            else:
                if not self.__tracking_icao24 in self.__observations:
                    self.__tracking_icao24 is None
                    continue
                cur = self.__observations[self.__tracking_icao24]
                if cur is None:
                    continue

                (lat, lon) = utils.calc_travel(cur.getLat(), cur.getLon(),
                                               cur.getLoggedDate(),
                                               cur.getGroundSpeed(),
                                               cur.getTrack(), camera_lead)
                distance = utils.coordinate_distance(camera_latitude,
                                                     camera_longitude, lat,
                                                     lon)
                # Round off to nearest 100 meters
                #distance = round(distance/100) * 100
                bearing = utils.bearing(camera_latitude, camera_longitude, lat,
                                        lon)
                elevation = utils.elevation(
                    distance, cur.getAltitude(), camera_altitude
                )  # we need to convert to feet because the altitude is in feet

                retain = False
                self.__client.publish(self.__tracking_topic,
                                      cur.json(bearing, distance, elevation),
                                      0, retain)
                logging.info(
                    "%s at %5d brg %3d alt %5d trk %3d spd %3d %s" %
                    (cur.getIcao24(), distance, bearing, cur.getAltitude(),
                     cur.getTrack(), cur.getGroundSpeed(), cur.getType()))

                if distance < 3000:
                    time.sleep(0.25)
                elif distance < 6000:
                    time.sleep(0.5)
                else:
                    time.sleep(1)
Ejemplo n.º 9
0
 def selectNearestObservation(self):
     """Select nearest presentable aircraft
     """
     self.__tracking_icao24 = None
     self.__tracking_distance = 999999999
     for icao24 in self.__observations:
         if not self.__observations[icao24].isPresentable():
             continue
         distance = utils.coordinate_distance(self.__latitude, self.__longitude, self.__observations[icao24].getLat(), self.__observations[icao24].getLon())
         if distance < self.__tracking_distance:
             self.__tracking_icao24 = icao24
             self.__tracking_distance = distance
     if self.__tracking_icao24 is None:
         logging.info("Found nothing to track")
     else:
         logging.info("Found new tracking %s at %d" % (self.__tracking_icao24, self.__tracking_distance))
Ejemplo n.º 10
0
    def update(self, sbs1msg):
        """ Updates information about a plane from an SBS1 message """

        oldData = dict(
            self.__dict__
        )  # save existing data to determine if anything has changed
        self.__loggedDate = datetime.utcnow()

        if sbs1msg["icao24"]:
            self.__icao24 = sbs1msg["icao24"].lower(
            )  # Let's always keep icao24 in lower case
        if sbs1msg["callsign"] and self.__callsign != sbs1msg["callsign"]:
            self.__callsign = sbs1msg["callsign"].rstrip()
        if sbs1msg["altitude"] is not None:
            if self.__altitude != sbs1msg["altitude"]:
                self.__altitude = sbs1msg["altitude"]
                self.__altitudeTime = sbs1msg["generatedDate"]
        if sbs1msg["groundSpeed"] is not None:
            self.__groundSpeed = sbs1msg["groundSpeed"]
        if sbs1msg["track"] is not None:
            self.__track = sbs1msg["track"]
        if sbs1msg["onGround"] is not None:
            self.__onGround = sbs1msg["onGround"]
        if sbs1msg["lat"] is not None:
            self.__lat = sbs1msg["lat"]
            self.__latLonTime = sbs1msg["generatedDate"]
        if sbs1msg["lon"] is not None:
            self.__lon = sbs1msg["lon"]
            self.__latLonTime = sbs1msg["generatedDate"]
        if sbs1msg["verticalRate"] is not None:
            self.__verticalRate = sbs1msg["verticalRate"]

        if not self.__verticalRate:
            self.__verticalRate = 0

        if self.__lat and self.__lon and self.__altitude and self.__track:
            # Calculates the distance from the cameras location to the airplane. The output is in METERS!
            distance3d = utils.coordinate_distance_3d(camera_latitude,
                                                      camera_longitude,
                                                      camera_altitude,
                                                      self.__lat, self.__lon,
                                                      self.__altitude)
            distance2d = utils.coordinate_distance(camera_latitude,
                                                   camera_longitude,
                                                   self.__lat, self.__lon)

            self.__distance = distance3d
            self.__bearing = utils.bearingFromCoordinate(
                cameraPosition=[camera_latitude, camera_longitude],
                airplanePosition=[self.__lat, self.__lon],
                heading=self.__track)
            self.__elevation = utils.elevation(
                distance2d,
                cameraAltitude=camera_altitude,
                airplaneAltitude=self.__altitude
            )  # Distance and Altitude are both in meters

        # Check if observation was updated
        newData = dict(self.__dict__)
        #del oldData["_Observation__loggedDate"]
        #del newData["_Observation__loggedDate"]
        d = DictDiffer(oldData, newData)
        self.__updated = len(d.changed()) > 0
Ejemplo n.º 11
0
 def updateTrackingDistance(self):
     """Update distance to aircraft being tracked
     """
     cur = self.__observations[self.__tracking_icao24]
     self.__tracking_distance = utils.coordinate_distance(self.__latitude, self.__longitude, cur.getLat(), cur.getLon())