If the location is a fixed value, I would simply not send it in the payload. It’s just a waste of payload size / airtime. If you really do want to send it, I would consider sending it as a separate message and use a different LoRaWAN port value (FPORT) to distinguish it from other measurement data.
You can then also make the position updates and sensor data messages relatively independent of each other. For example you can send it on a different time schedule (say only once per day for position) or with a different encoding.
You just need to add the location as I described above. The format of the JSON will be correct. (Thai is if your decoder is correct for the air quality values)
You need to add the MQTT integration for the Application, give them the User name and API key. They then just need to subscribe.
below the payload I use. I really do not know how to get the Longitude and Latitude in there in JSON. Sorry. I put the L&L in the TTN console but do not see the value in the uplink.
Marc
function Decoder(bytes, port) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var measurementTypes = ["Mass Concentration PM1.0", "Mass Concentration PM2.5", "Mass Concentration PM4.0", "Mass Concentration PM10", "Number Concentration PM0.5", "Number Concentration PM1.0", "Number Concentration PM2.5", "Number Concentration PM4.0", "Number Concentration PM10", "Typical Particle Size"];
var decoded = {};
if(port != 223)
{
decoded.Battery = (bytes[0] & 0x0F)/10 + 2;
// decoded.Battery = (bytes[0] & 0x0F)/10 + 2 + " V";
}
if (port == 1) {
var pmconfig = bytes[1] << 8 | bytes[2];
var estimatedsize = 3;
var index = 3;
for (var i = 9; i >= 0; i--) {
bit = pmconfig & (1 << i);
if(bit){
decoded[measurementTypes[(9-i)]] = parseFloat(bytes[index] << 24 | bytes[index+1] << 16 | bytes[index+2] << 8 | bytes[index+3]);
index +=4;
estimatedsize +=4;
}
}
if(estimatedsize < bytes.length){
decoded.temperature = (bytes[bytes.length-4] << 8 | bytes[bytes.length-3]) / 100;
decoded.humidity = (bytes[bytes.length-2] << 8 | bytes[bytes.length-1]) / 100;
}
}
function parseFloat(bits) {
var sign = ((bits >>> 31) === 0) ? 1.0 : -1.0;
var e = ((bits >>> 23) & 0xff);
var m = (e === 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000;
var f = sign * m * Math.pow(2, e - 150);
return f;
}
return decoded;
This is from a temperature sensor so the decoded payload is different, but you can see the location properties. It also take a few uplinks before it will appear.