[SOLVED] Setup Tabs GPS sensor & Ubidots

I’m connecting the Tabs GPS Tracker to Ubidots and I’m facing issues with the GPS map.

The payload format I used:

function bits(value, lsb, msb) {
  var len = msb - lsb + 1;
  var mask = (1<<len) - 1;
  return value>>lsb & mask;
}

function Decoder(bytes, port) {
  var status = bits(bytes[0], 0, 7);
  var voltage = (25 + bits(bytes[1], 0, 3)) / 10;
  var bat_percentage = 100 * ((bits(bytes[1], 4, 7)) / 15);
  var temp = bits(bytes[2], 0, 7) - 32;
  var lat = ((((bytes[6] << 24) | bytes[5] << 16) | bytes[4] << 8) | bytes[3])/1000000;
  var lon = ((((bytes[10] << 24) | bytes[9] << 16) | bytes[8] << 8) | bytes[7])/1000000;
  var position = {"lat": lat, "lng": lon};

  var json={
    voltage:voltage,
    bat_percentage:bat_percentage,
    temp:temp,
    position:position,
    lat: lat,
    lon: lon
  }
  
    return json;
  }

This gives the following output in the console:

Screenshot 2020-02-17 at 16.57.52

The output in Ubidots:
Screenshot 2020-02-17 at 17.04.30

Somehow, the Latitude and Longitude are not recognized.

Any ideas?

@ubidots

An example from Ubidots on the forum uses the following JSON format:

So, maybe remove the excessive "lat" and "lon" properties that are on the JSON’s root level in your output? (Also note the "lon" vs "lng".)

Also, an October 2019 screenshot in the same post shows “Location Mode: auto”, and does not define an orange “Variable” box for the position value. What if you remove that? (Maybe explicitly mapping the position variable stops it from being used for the map?)

I found some support via the Ubidots forum, see forwarded message below. This works like a charm.

The payload being sent does not manage the correct format. If you refer to the Ubidots API documentation, you will notice that the payload must contain the following format:

{"position": {"value" : 1, "context":{"lat":-6.2, "lng":75.4}}}

In your case, the payload should be:

  var json={
    voltage:voltage,
    bat_percentage:bat_percentage,
    temp:temp,
    position:{"value":1, "context": position},
    lat: lat,
    lon: lon
  }

Aside: your payload decoder seems to be using some bits that are documented as being reserved for future use.

Like for temperature, bits(bytes[2], 0, 7) returns all 8 bits (and would be the same as just bytes[2]), but the leftmost bit 7 is RFU. So that should read bits(bytes[2], 0, 6).

Same goes for some bits in the coordinates, which in your case happen to be positive values so you won’t notice the RFU’s in latitude being zeroes (as long as one does not upgrade the firmware). But for negative values you’d need sign extension to compensate for those zeroes.

For longitude, I think you are already running into an error if the GNSS accuracy is 8 meter or worse: you’re using all 8 bits of bytes[10] for the longitude, while the leftmost bits 29-31 indicate the accuracy, which will not be zeroes for lower accuracy. And that also needs sign extension.

So, I’d say that should read:

// Leftmost bit 7 is RFU
var temp = bits(bytes[2], 0, 6) - 32;

// Use only 4 bits of the MSB, and sign-extend those to support 
// negative values, by shifting 4 bits too far to the left
// followed by a sign-extending shift to the right:
var lat = (bits(bytes[6],0, 3) << 28 >> 4 
  | bytes[5] << 16 | bytes[4] << 8 | bytes[3])/1000000;

// Likewise, using 5 bits of the MSB
var lon = (bits(bytes[10], 0, 4) << 27 >> 3 
  | bytes[9] << 16 | bytes[8] << 8 | bytes[7])/1000000;

// A value of 512 actually denotes worse than 256 meter
var accuracy = 1 << (bits(bytes[10], 5, 7) + 2);

payload

1 Like

Thanks for the additions Arjan!

In fact, later I found I already posted a slightly simpler approach for a decoder for the same device:

I guess a 7:16 PM post is better than a 0:17 AM post. :wink:

1 Like

Thanks @laurens and @arjanvanb for sharing the “context” workaround, and at the same time bringing to our attention an issue when posting the position as a tuple {"lat": 52.395316, "lng": 4.874904}.

Both requests are equivalent. The problem was we recently deployed a new version of our ingestion layer, which was causing an issue when using the position tuple. As soon as we saw your note, our team deployed a fix and now things are back to normal.

As a recap, these two formats are valid and equivalent in Ubidots API:

{"position": {"lat": 6.2, "lng": -75.4}}

or

{"position": {"value" : 1, "context":{"lat":-6.2, "lng":75.4}}}

2 Likes