ecosoph
(Markovicz)
April 21, 2020, 6:10am
1
Good morning TTN-Fellows,
I would like to use the Adeunis field tester:
along with TTNMapper. What is the recommended procedure right now? Is turning on the TTNMapper integration sufficient or should I use the payload decoder developed here:
https://www.thethingsnetwork.org/labs/story/payload-decoder-for-adeunis-field-test-device-ttn-mapper-integration
The latest discussion is already two years old:
tnx, I always understand that the Adonis Field test device transmitted a confirmed packet and then received info back about the RSSI/SNR (if in range and for multiple GW)
Thanks for your time guys!
pe1mew
(Remko)
April 23, 2020, 7:00am
2
I have run a quick test and did not find that TTN Mapper is using Adeunis data.
The story you refer to is very incomplete. We might ask @jpmeijers for an answer.
Hi @ecosoph . You will need the payload decoder configured on the TTN Console. Then if you enable the TTN Mapper integration the parsed payload fields will be sent to TTN Mapper. If you don’t have a payload decoder configured that spits out latitude and longitude, TTN Mapper does not know what to do with the data and discards it.
A quick glance over that parser you linked. It should work, but the quality of the code doesn’t look great. I see a lot of conversion between numbers to strings and back to numbers.
1 Like
pe1mew
(Remko)
April 24, 2020, 1:40pm
4
I have added the payload.lat and payload.lon to the custom payload-script and added TTN-Mapper integration to the application and it works fine:
This is the modified code:
// 24-4-2020, remko@rfsee.nl, Modification to add payload.lat en lon to make compatible with TTN
function Decoder( bytes, port ){
// Functions
function parseCoordinate( raw_value, coordinate ){
// This function parses a coordinate payload part into
// dmm and ddd
var raw_itude = raw_value;
var temp = "";
// Degree section
var itude_string = ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
itude_string += ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
coordinate.degrees += itude_string;
itude_string += "°";
// Minute section
temp = ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
temp += ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
itude_string += temp;
itude_string += ".";
coordinate.minutes += temp;
// Decimal section
temp = ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
temp += ( (raw_itude >> 28) & 0xF ).toString( );
raw_itude <<= 4;
itude_string += temp;
coordinate.minutes += ".";
coordinate.minutes += temp;
return itude_string;
}
function parseLatitude( raw_latitude, coordinate ){
var latitude = parseCoordinate( raw_latitude, coordinate );
latitude += ((raw_latitude & 0xF0) >> 4).toString( );
coordinate.minutes += ((raw_latitude & 0xF0) >> 4).toString( );
return latitude;
}
function parseLongitude( raw_longitude, coordinate ){
var longitude = ( ((raw_longitude >> 28) & 0xF ) ).toString( );
coordinate.degrees = longitude;
longitude += parseCoordinate( raw_longitude << 4, coordinate );
return longitude;
}
function addField(field_no, payload){
switch(field_no){
// Presence of temperature information
case 0:
payload.temperature = bytes[bytes_pos_] & 0x7F;
// Temperature is negative
if((bytes[bytes_pos_] & 0x80) > 0 ){
payload.temperature -= 128;
}
bytes_pos_++;
break;
// Transmission triggered by the accelerometer
case 1:
payload.trigger = "accelerometer";
break;
// Transmission triggered by pressing pushbutton 1
case 2:
payload.trigger = "pushbutton";
break;
// Presence of GPS information
case 3:
// GPS Latitude
// An object is needed to handle and parse coordinates into ddd notation
var coordinate = {};
coordinate.degrees = "";
coordinate.minutes = "";
var raw_value = 0;
raw_value |= bytes[bytes_pos_++] << 24;
raw_value |= bytes[bytes_pos_++] << 16;
raw_value |= bytes[bytes_pos_++] << 8;
raw_value |= bytes[bytes_pos_++];
payload.lati_hemisphere = (raw_value & 1) == 1 ? "South" : "North";
payload.latitude_dmm = payload.lati_hemisphere.charAt( 0 ) + " ";
payload.latitude_dmm += parseLatitude( raw_value, coordinate );
payload.latitude = ( parseFloat( coordinate.degrees ) + parseFloat( coordinate.minutes ) / 60 ) * ( (raw_value & 1) == 1 ? -1.0 : 1.0);
payload.lat = payload.latitude;
// GPS Longitude
coordinate.degrees = "";
coordinate.minutes = "";
raw_value = 0;
raw_value |= bytes[bytes_pos_++] << 24;
raw_value |= bytes[bytes_pos_++] << 16;
raw_value |= bytes[bytes_pos_++] << 8;
raw_value |= bytes[bytes_pos_++];
payload.long_hemisphere = (raw_value & 1) == 1 ? "West" : "East";
payload.longitude_dmm = payload.long_hemisphere.charAt( 0 ) + " ";
payload.longitude_dmm += parseLongitude( raw_value, coordinate );
payload.longitude = (parseFloat(coordinate.degrees) + parseFloat(coordinate.minutes)/60) * ((raw_value & 1) == 1 ? -1.0 : 1.0);
payload.lon = payload.longitude;
// GPS Quality
raw_value = bytes[bytes_pos_++];
switch((raw_value & 0xF0) >> 4 ){
case 1:
payload.gps_quality = "Good";
break;
case 2:
payload.gps_quality = "Average";
break;
case 3:
payload.gps_quality = "Poor";
break;
default:
payload.gps_quality = (raw_value >> 4) & 0xF;
break;
}
payload.hdop = (raw_value >> 4) & 0xF;
// Number of satellites
payload.sats = raw_value & 0xF;
break;
// Presence of Uplink frame counter
case 4:
payload.ul_counter = bytes[bytes_pos_++];
break;
// Presence of Downlink frame counter
case 5:
payload.dl_counter = bytes[bytes_pos_++];
break;
// Presence of battery level information
case 6:
payload.battery_level = bytes[bytes_pos_++] << 8;
payload.battery_level |= bytes[bytes_pos_++];
break;
// Presence of RSSI and SNR information
case 7:
// RSSI
payload.rssi_dl = bytes[bytes_pos_++];
payload.rssi_dl *= -1;
// SNR
payload.snr_dl = bytes[bytes_pos_] & 0x7F;
if( (bytes[bytes_pos_] & 0x80) > 0 ){
payload.snr_dl -= 128;
}
bytes_pos_++;
break;
default:
// Do nothing
break;
}
}
// Declaration & initialization
var status_ = bytes[0];
var bytes_len_ = bytes.length;
var bytes_pos_ = 1;
var i = 0;
var payload = {};
// Get raw payload
var temp_hex_str = ""
payload.payload = "";
for( var j = 0; j < bytes_len_; j++ ){
temp_hex_str = bytes[j].toString( 16 ).toUpperCase( );
if( temp_hex_str.length == 1 ){
temp_hex_str = "0" + temp_hex_str;
}
payload.payload += temp_hex_str;
}
// Get payload values
do{
// Check status, whether a field is set
if((status_ & 0x80) > 0 ){
addField(i, payload);
}
i++;
}while(((status_ <<= 1) & 0xFF) > 0 );
return payload;
}