Can't pass geolocation object with Meteor.call (but anything else works!)


#1

I’m trying to pass the result from navigator.geolocation.watchPosition() to the server with Meteor.call, but all I get is an empty object.

If I pass any other object, it arrives just fine. As a workaround I’m mapping the relevant attributes of the geolocation object to a new object, but I’d rather just pass it in intact.

Code snippets:

//collections/tracks.js
Tracks = new Ground.Collection("tracks");

Meteor.methods({
  addPosition(position) {
    console.log("in addPosition", position);
    check(position, Object);
    Tracks.insert(position);
  }
});
//server/server.js
Meteor.publish("tracks", function () {
  return Tracks.find({
  });
});
//client/client.js
Meteor.subscribe("tracks");
[...]
onSuccess: function(position) {
  Meteor.call("addPosition", position)
}
[...]
watchId = navigator.geolocation.watchPosition(this.onSuccess, this.onError });


#2

Try console.log the typeof that object. May not be just an object. You may have to serialize or convert it to a normal object.


#3

From the code you show, your onSuccess function is passing you a position, and your passing this.state.position into the function when you should just be passing position?

onSuccess: function(position) {
  Meteor.call("addPosition", position)
}

If thats not the issue make sure your not getting any errors through the error handler.


#4

Thanks @lucfranken - pardon my ignorance, but when is an object not an object? (Coming from Ruby where everything is an object in the truest sense of the word, it seems to have multiple meanings in JS).

The browser shows it as Geoposition {}

How would I go about converting it to an object? Thanks!


#5

read what argument there could be http://docs.meteor.com/#/full/meteor_call
most of DDP/Meteor related stuff counts with E-JSON, not any object. http://docs.meteor.com/#/full/ejson


#6

Thanks @pmwisdom - that was a transcription error while trying to simplify the example code. I am currently copying some of the object attributes to this.state, but should have changed that for the “raw” object.

There are no errors in the error handler, and I can log the geolocation object to the console.


#7

@shock Hm, okay thanks. Not sure how DDP would view it, but there are no unusual datatypes in the Geoposition object (numbers basically). You can try it in the browser console:

navigator.geolocation.getCurrentPosition((it) => {console.log(it)})

#8

@mbrookes Your going to have to provide more code then that to successfully help you out then. You’ve omitted most of the code that could help us help you. When your onSuccess fires, if you console.log(position) does it read out the correct geolocation object in the console?

The way you’ve written it it looks like your geolocation call is outside of your React class.


#9

@pmwisdom, not sure what’s missing to debug. I’m not a big fan of dumping a ton of code and expecting others to pick through it and find the relevant bits, so that should be all the pertinent code. I also intentionally tried to “de-React” it (being a Meteor specific question), but missed this.state - I’ll edit that.

To your question though (and thanks for helping), yes, console.log(position) in onSuccess valid.


#10

while playing in browser console

    testObject = {prop1: "test1", prop2: "test2"}
    Object {prop1: "test1", prop2: "test2"}
    EJSON.toJSONValue(testObject)
    Object {prop1: "test1", prop2: "test2"}
    navigator.geolocation.getCurrentPosition((it) => {console.log(EJSON.toJSONValue(it))})
    undefined
    Object {}

maybe it is time to pass location.coords instead of whole object with all these proto functions and stuff.


#11

Thanks @shock - guess I was doing it right all along, just didn’t know why. So much to learn!


#12

And even coords prop will not be enough cause it has some stuff there which cannot be packed seems.
it.coords.longitude is OK etc etc
Now try it in your usecase and let us know.

Maybe I am also just misleading you :smiley: It is 1:45am here

And I am kinda exhausted from all these APIs of mine little project - search engine above all livestreams solutions I can think of : youtube, twitch, hitbox, periscope, meerkat . And I am noob in elasticsearch, so indexing like total noob :frowning:


#13

@shock is correct!

You can use my package if you’d like. I tested it and this works with my package. https://atmospherejs.com/mirrorcell/geolocation-plus

if(Meteor.isClient) {
Location.locate(function(pos) {
    console.log("Look at me, position object", pos);
    Meteor.call('addPosition', pos);
})
}

if(Meteor.isServer) {
Meteor.methods({
    addPosition: function(pos) {
        console.log("SERVER POSITION", pos);
    }
})
}

#14

An object can have a type. So a car and a bike are both an object. For example the car has an engine but the bike does not.

Here is a quite simple example showing objects with different types:

Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(function () {}); // [object Function]

#15

I know the feeling. I wrote a ruby library to standardise across multiple media APIs Apple Music, Amazon, XBox music (as it was then)… It’s a nightmare.


#16

And DDP only supports certain object types… Got it, thanks!


#17

Looks good, thanks. Does it use native GPS in cordova, or is it a wrapper to the HTML5 API? I think I’m going to need support for background GPS (realtime sports tracker app), but no idea how that works…


#18

Correct and you should validate it in the method to be sure you receive an object with the right parameters: http://docs.meteor.com/#/full/matchpatterns

That package seems good, anyhow it’s better to use a package for this. In this file you can see whether it uses Cordova plugins:

This package seems to be about background:
https://atmospherejs.com/zeroasterisk/cordova-geolocation-background

Interesting thing I found is:
https://atmospherejs.com/mdg/geolocation because this one has a method which seems to return just a normal object:

Geolocation.latLng()
A simple shorthand for currentLocation() when all you need is the latitude and longitude. Returns an object that has lat and lng keys.

So MDG did see a reason to supply it. Maybe the other packages also support such a thing.


#19

Everything @lucfranken said was correct. For background you must use as background tracker, as he linked. Just be sure to be careful when using that one. It uses an older version of Christocracys background plugin. Which hasn’t been updated (for the general non paying public) in a long, long time.

Edit: Addendum, that plugin may or may not work for you depending on your requirements and how many data points you need while using it. It uses whats called geolocation fences and the iOS significant changes library to start and stop geolocation tracking. For example your phone will get one point every few blocks, and then a stream of point after that, and then rinse and repeat.

Geolocation.latLng() is probably geared at giving you an easy object back to interface with things like google maps where all positions are handled via LatLng objects.


#20

Thanks both - seems I am going to struggle then with background GPS with the available cordova plugins, and the commercial version is way above my budget for a personal project. I’ll just have to tell the user to keep the app open I guess. :-/