summaryrefslogblamecommitdiffstats
path: root/iss_get_data.js
blob: 0db03c86a242e600384617e2855d3237fbce7799 (plain) (tree)
1
2
3
4
5
6
7
              
                                      
                    
                           
                                  

                                   








                       

                                                          



































                                                                           

















                                                                       
























                                                                            
                                           







                                                                       
 



                                                                    



                                






































                                                                     

                             

                                








                                                                    







                             

               
#!/usr/bin/gjs
/* jshint moz: true, multistr: true */
/* global imports */
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const GObject = imports.gi.GObject;
const Lang = imports.lang;

const AccuracyLevel = {
    COUNTRY: 1,
    CITY: 4,
    NEIGHBORHOOD: 5,
    STREET: 6,
    EXACT: 8
};

const API_URL = 'http://api.open-notify.org/iss-now.json';

const ManagerIface = '<node> \
  <interface name="org.freedesktop.GeoClue2.Manager"> \
    <method name="GetClient"> \
      <arg type="o" name="client" direction="out"/> \
    </method> \
  </interface> \
</node>';
const ManagerProxy = Gio.DBusProxy.makeProxyWrapper(ManagerIface);

const ClientInterface = '<node> \
<interface name="org.freedesktop.GeoClue2.Client"> \
    <property name="Location" type="o" access="read"/> \
    <property name="DesktopId" type="s" access="readwrite"/> \
    <property name="RequestedAccuracyLevel" type="u" access="readwrite"/> \
    <property name="DistanceThreshold" type="u" access="readwrite"/> \
    <property name="Active" type="b" access="read"/> \
    <method name="Start"/> \
    <method name="Stop"/> \
    <signal name="LocationUpdated"> \
        <arg name="old" type="o"/> \
        <arg name="new" type="o"/> \
    </signal> \
</interface> \
</node>';
const ClientProxy = Gio.DBusProxy.makeProxyWrapper(ClientInterface);

const LocationInterface = '<node> \
<interface name="org.freedesktop.GeoClue2.Location"> \
    <property name="Latitude" type="d" access="read"/> \
    <property name="Longitude" type="d" access="read"/> \
    <property name="Accuracy" type="d" access="read"/> \
    <property name="Description" type="s" access="read"/> \
</interface> \
</node>';
const LocationProxy = Gio.DBusProxy.makeProxyWrapper(LocationInterface);

const ISS_Above = new GObject.Class({
  Name: 'ISS_Above',
  Extends: GObject.Object,
  Signals: {
    'processed_data': {
      param_types: [
        // GObject.TYPE_INT
      ]
    }
  },

  _init: function(params) {
    this.parent(params);

    this.managerProxy = new ManagerProxy(Gio.DBus.system,
      'org.freedesktop.GeoClue2', '/org/freedesktop/GeoClue2/Manager');

    [this.clientAddr] = this.managerProxy.GetClientSync();

    this.current_location = {};
    this.iss_coords = null;
    this.task_queue = 2; // number of async process to complete

    this.clientProxy = new ClientProxy(Gio.DBus.system,
        'org.freedesktop.GeoClue2', this.clientAddr);
    this.clientProxy.DesktopId = 'gnome-shell-ISS_Above';
    this.clientProxy.DistanceThreshold = 10000;
    this.clientProxy.RequestedAccuracyLevel = AccuracyLevel.EXACT;
    this.clientProxy.connectSignal('LocationUpdated',
        Lang.bind(this, this.onLocationUpdated));
    this.clientProxy.StartRemote();
    this.connect('processed_data', Lang.bind(this, this.processResult));
  },

  run: function() {
    this.getISScoords();
  },

  getISScoords: function () {
    let self = this;
    let iss_api = Gio.file_new_for_uri(API_URL);
    iss_api.load_contents_async(null, function(iss_api, result) {
      self.iss_coords = JSON.parse(iss_api.load_contents_finish(result)[1]);
      // print(self.iss_coords.toSource());
      self.emit('processed_data');
    });
  },

  onLocationUpdated: function (proxy, sender, [oldPath, newPath]) {
    let geoclueLocation = new LocationProxy(Gio.DBus.system,
                                            "org.freedesktop.GeoClue2",
                                            newPath);

    this.current_location.Latitude = geoclueLocation.Latitude;
    this.current_location.Longitude = geoclueLocation.Longitude;
    this.current_location.Accuracy = geoclueLocation.Accuracy;
    this.current_location.Description = geoclueLocation.Description;

    this.emit('processed_data');
  },

  /** 
   * Calculate distance in km of two geographical points
   *
   * @param lat1  Number latitude of the first point
   * @param long1 Number longitude of the first point
   * @param lat2  Number latitude of the second point
   * @param long2 Number longitude of the second point
   * @return Number distance in km
   *
   * Described on https://en.wikipedia.org/wiki/Haversine_formula
   */
  get_distance: function(lat1, long1, lat2, long2) {
    // Mean radius of the Earth in km
    const EARTH_R = 6371;
    const PI_180 = Math.PI / 180;

    function haversin(fi) {
      return (1 - Math.cos(fi)) / 2;
    }

    lat1 = lat1 * PI_180;
    long1 = long1 * PI_180;
    lat2 = lat2 * PI_180;
    long2 = long2 * PI_180;

    let dist = 2 * EARTH_R *
      Math.asin(Math.sqrt(haversin(lat2 - lat1) +
        Math.cos(lat1) * Math.cos(lat2) * haversin(long2 - long1)));

    let test_haversin = haversin(dist / EARTH_R);
    if (test_haversin < 1) {
      return dist.toFixed(3);
    }
    else {
      throw new Error('haversine(d/r) cannot be over 1, but it is ' +
          test_haversin);
    }
  },

  processResult: function() {
    this.task_queue--;

    if (this.task_queue === 0) {
      // print('our location: ' + this.current_location.toSource());
      // print('iss coordinates: ' + this.iss_coords.toSource());

      let dist = this.get_distance(this.current_location.Latitude,
          this.current_location.Longitude,
          this.iss_coords.iss_position.latitude,
          this.iss_coords.iss_position.longitude)

      print('ISS is ' + dist + ' km away.');

      Mainloop.quit();
    }
  }
});

let client = new ISS_Above();
client.run();

Mainloop.run();