IoT Central map gps long/lat format

I’m sure this should be really simple to find but i can’t see this info anywhere.

What is the required format for the location property on Iot Central? I can see it is geopoint but i have formatted my data as per the below and this doesn’t work:

"gps":"lat: 53.065151, lon: -2.478252"

The code i use to construct this is:

location_format =("lat:"+ String(GPS.latitudeDegrees) + ",lon:" + String(GPS.longitudeDegrees));  

I then use Json to format the final message.

gps is the data handle, i can see the data is sat against the correct data handle in raw data but none of the map tiles are working so i am presuming i have the wrong format?

This is not valid JSON.
You may want to wrap lat/lon in a separate set of curly braces like this

  "gps": { "lat": 53.065151, "lon": -2.478252 }

or like this

  "gps": "{ lat: 53.065151, lon: -2.478252 }"

If that doesn’t work you could try the more elaborate version

{
  "Location":{
    "value":{
      "lat":53.065151,
      "lon":-2.478252
    }
  }
}

I feel like i’m getting closer with this but still not quite got it. I’ve played around with your suggestion and can’t quite get it to work. I am using JsonParserGeneratorRK and i believe i need to add 2 values to one key. I have tried this several ways and it’s still not quite right, can someone please explain how i insert two values with one key, the code i have tried so far is:

void createEventPayload(int temp, String location_format, float longi, float lati)
{
  JsonWriterStatic<256> jw;
  {
    char data[256];
		//snprintf(data, sizeof(data), "{\"lat\":%f, \"lon\":%f}", lati, longi);
    snprintf(data, sizeof(data), "{\"lat\":%f, \"lon\":%f}", lati, longi);

    JsonWriterAutoObject obj(&jw);
    jw.insertKeyValue("temp", temp);
    jw.insertKeyValue("gps", data);
    jw.insertKeyValue("lat", lati);
    jw.insertKeyValue("lon", longi);
    
  }
    Particle.publish("Test_data", jw.getBuffer(), PRIVATE);

The output i am receiving is:

{
"temp":27
"gps":"{"lat":53.065170, "lon":-2.478283}"
"lat":53.06517
"lon":-2.478283
}

I think what i am really after is the output to read

{
"temp":27
"gps": lat:53.065170, lon:-2.478283
"lat":53.06517
"lon":-2.478283
}

Finally - The particle webhook has the below JSON and i am not 100% sure if this needs to be changed?


          
{
  "device": {
    "deviceId": "{{{PARTICLE_DEVICE_ID}}}"
  },
  "measurements": {{{PARTICLE_EVENT_VALUE}}}
}

I am not the greatest coder so any explanation as to what might be going on would be very helpful.

AFAICT your gps field should not be a string element but rather another JSON object.
I’m not certain how that would be done with @rickkas7’s JSON generator tho’.

I’ve spent most of the day trying to debug this and it’s bizarre, i think i’ve now managed to get everything in the right place but i still get blank maps “Awaiting Data”. I have tried both with and wihout lat: lon: and that made no difference. I don’t really know who to ask as Microsoft don’t appear to offer any kind of support?

My code to get to this point is (summarised a little):

location_format =(String(GPS.latitudeDegrees) + "," + String(GPS.longitudeDegrees));
createEventPayload(27,location_format,longi,lati); 


void createEventPayload(int temp, String location_format, float longi, float lati)
{
  temp=32;
  JsonWriterStatic<256> jw;
  {   
    JsonWriterAutoObject obj(&jw);
    jw.insertKeyValue("temp", temp);
    jw.insertKeyValue("gps", location_format);
    
  }
    Particle.publish("Test_data", jw.getBuffer(), PRIVATE);
     Serial.println("Sent Test Data");
     Serial.println(jw.getBuffer());


}

image

Hi,
I assuming that you are using Adafruit_GPS library and then you created an object called “GPS to obtain latitudeDegrees and longitudeDegrees which are float type.
So I think that maybe there is still some issue with your JSON
I don’t have Adafruit GPS module but I was able to make some test after modifying your createEventPayload() function

void createEventPayload(int temp, float longi, float lati)
{
  //JsonWriterStatic<256> jw;
  
    char data[] = "{\"temp\":%d,\"gps\":{\"lat\":%f,\"lon\":%f},\"lat\":%f,\"lon\":%f}";
    char finall[sizeof(data) + 32];
    snprintf(finall, sizeof(finall), data, temp, lati, longi, lati, longi);
    
    Particle.publish("Test_data", finall, 60, PRIVATE);
}

I just call the function like this
createEventPayload(32, 52.0764, 54.1765); for testing JSON
but you can do it like this:
createEventPayload(32, GPS.longitudeDegrees, GPS.latitudeDegrees);
and the output looks like one of yours above and is valid JSON format

Thanks @dreamER this is getting me much closer (i think)!

I have a few questions about the code.

char finall[sizeof(data) + 32];

I understand the general concept of +32 but why do we need it? does sizeof(data) not set the size?

Particle.publish("Test_data", finall, 60, PRIVATE);

What is the 60?

I can now see the JSON appears in the correct format in particle as per your example. I have finally found the document that shows the JSON requirements for azure geopoint and i believe i am now sending the right JSON but still the map doesn’t show.

The below shows the requirements for azure, JSON is completely new to me and so i don’t understand the reference to a DCM? Do i need to do something with the first block? Do i need to add the schema so that Azure knows it’s a geopoint? Although i would have thought this is covered in the mapping of my GPS object?

Taken from https://docs.microsoft.com/en-us/azure/iot-central/core/concepts-telemetry-properties-commands

### Complex types

This section shows examples of complex telemetry types that a device streams to an IoT Central application.

The following snippet from a DCM shows the definition of a geopoint telemetry type:

{
  "@id": "<element id>",
  "@type": "Telemetry",
  "displayName": {
    "en": "GeopointTelemetry"
  },
  "name": "GeopointTelemetry",
  "schema": "geopoint"
}

A device client should send the telemetry as JSON that looks like the following example. IoT Central displays the value as a pin on a map:

{
  "GeopointTelemetry": {
    "lat": 47.64263,
    "lon": -122.13035,
    "alt": 0
  }
}

Thank you for your help thus far it is very helpful.

Not quite. sizeof() requests the current size of the format string (data[]) to then set the desired/expected size of the new string (finall[]) based on that (plus any extras).
But the format string only contains the format placeholders, which only are 2 characters long. So when you then "stuff" these placeholders with the actual content the string will become longer than the pattern string itself. For that extra length you need to account for to avoid memory corruption.

Typically you would not have the pattern string as automatic variable inside the function but rather as const char statically stored in flash.

BTW, +32 may be on the tight side :wink: Having a negative two-digit temperature and also multiple negative three-digit lat/lon readings with 5-6 decimal places would even outgrow that extra space.

That is a dormant parameter which would set the Time To Live (default 60 seconds) for the event. But TTL has never been implemented and hence can be omitted entirely.

1 Like

Thanks @ScruffR, that’s what i thought it was, i have added in altitude which then in turn extended the string beyond it’s ‘allocation’ and after changing the 32 i then started to see the full string again but thanks for the explanation. Now i’ve just got to get the map to show!

1 Like

Ok, the only last difference i can see between what i get as an output and the required JSON format is the missing commas after the long and lat values. How would i add these in? Also what do i need to google to find out about the format you have used to construct the JSON, i’m not familiar with the “”\ format.

Current output:


Current code:

char data[] = "{\"temp\":%d,\"gps\":{\"lat\":%f,\"lon\":%f,\"alt\":%f},\"lat\":%f,\"lon\":%f}";

How would i add commas after the value to make the output show:

    "lat": 47.64263,
    "lon": -122.13035,
    "alt": 0

Hi, I guess that those comma are there but for some reason Particle console doesn’t show them
you can copy the RAW data from Particle console and then check here is a JSON Validator and I’m positive that they gonna be visible.
Regarding The Microsoft stuff to be onset I don’t know nothing about it so I’ll have to spend some time to get into this.
Thanks @ScruffR for excellent explanation :+1:

1 Like

I’ve used the Azure CLI to validate the JSON and i can see everything matches the requirements with no errors, i’ve contacted Microsoft, i’m just amazed that i am the only person to see this problem and i’m shocked at the lack of documentation out there, very frustrating.

Thanks to all who have helped with this as initially my JSON was incorrect and you’ve certainly helped my understanding so thanks for putting up with me!

Hey @Joshbailz maybe the issue is with your key "gps" could you change it to "GeopointTelemetry" and then try ?
try to change your function createEventPayload() for something like this:

void createEventPayload( float longi, float lati, float alt)
{
  //JsonWriterStatic<256> jw;
  
    char data[] = "{\"GeopointTelemetry\":{\"lat\":%f,\"lon\":%f,\"alt\":%f}}";
    char finall[sizeof(data) + 128];
    snprintf(finall, sizeof(finall), data, lati, longi, alt);
    
    Particle.publish("Test_data", finall, 60, PRIVATE);
}

and then try it again. Some pic for reference :+1:

this is from MS doc:

!

This from JSON Validator:

From_JSON_V !

and this is RAW data from Particle console:

Geo_raw !

@dreamER i tried changing the key and had the same results. I also added a post to stackpath and one of the suggestions is to try and simulate a device first, i will do this this morning and report back.

1 Like

I finally got it working, unfortunately only by starting again and deleting everything i had done thus far, as soon as i recreated my IoTC app and reimplemented the function that deals with the webhook everything worked perfectly. Still strange as the data format and everything else remained unchanged. But thank you for your help.