Cannot see the decoder result in "Events"

Hello Everybody

I’m using Chirpstack v4.0 and cannot see in “Events” the decoder results

When run this command “sudo journalctl -f -n 100 -u chirpstack”, i see this error: ERROR chirpstack::api::internal: Reading event-log returned error: Cannot serialize NaN as google.protobuf.Value.number_value. Someone knows this error?

Thanks

Are you certain that the javascript you supplied in the device profile runs and also gives expected output when fed “raw” data from the Device Data tab?

(example of what you’re looking for; this is for my sensor)
image

Si, finally I solved the problem. The cause is how to take bytes array, because I need define the function “function decodeUplink(input)” and later take the bytes as “input.bytes”

Previously I defined “function decodeUplink(bytes,fPort)” and that not working.

Thanks for response :slight_smile:

immagine

Iam facing the same problem as you did i believe.

Simply replacing “function decodeUplink(bytes,fPort)” with “function decodeUplink(input)” doas not solve the problem completely… so what else did you do?

Can I see your decoder for understand the problem??

This is my codec.
It seems the codec format has changed betver chirpstack v3 & v4…

// Decode decodes an array of bytes into an object.
// - fPort contains the LoRaWAN fPort number
// - bytes is an array of bytes, e.g. [225, 230, 255, 0]
// The function must return an object, e.g. {“temperature”: 22.5}
//function Decode( fPort, bytes )
function decodeUplink(input)

{

// 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);

// 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);

// 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;

}

Try to change all the parts “bytes” by “input.bytes”. For example, var status_ = bytes[0]; → var status_ = input.bytes[0];

The return code part, change “return payload” by “return: return { data: { payload} }”

I went back to the docs and found the part with ttn device integration and did that and lots of devices appeared, however it seems the adeunis fdt lacked codec but i did some googling and located a ttn v3 codec for the adeunis fdt here Adeunis FTD TTNMAPPER java script - The Things Stack v3 - The Things Network which worked when i put it in the template!!

Thanks anyway @Marcio_Mjqo !!

A lot has changed in v4 from v3 chirpstack… :slight_smile:

I understand, if it helps you this is the Adeunis decoder that I use in Chirpstack v4.

function decodeUplink(input) {
var fport_def = input.fPort
var bytes_def = input.bytes
if (fport_def==1){
var index = [1,2,6,13];
var status = bytes_def[0];
var gap = 0;
var latlon = [];
var latitudine = [];
var longitudine = [];
var battery = [];
var rssi = [];
var snr = [];
var bat = [];
var bot = [];
if (status&0x80){
}
else{
gap=gap-1;
}
if (status&0x10){
latitudine = bytes_def.slice(index[1]+gap,index[1]+gap+4);
longitudine = bytes_def.slice(index[2]+gap,index[2]+gap+4);
var lat = (latitudine[0]>>4)*10+(latitudine[0]&0xF)+((latitudine[1]>>4)*10+
(latitudine[1]&0xF)+(latitudine[2]>>4)*0.1+
(latitudine[2]&0xF)*0.01+(latitudine[3]>>4)*0.001)/60;
var lon = (longitudine[1]>>4)+((longitudine[1]&0xF)*10+(longitudine[2]>>4)+
(longitudine[2]&0xF)*0.1+(longitudine[3]>>4)*0.01)/60;
}
else{
gap=gap-9;
latitudine = 0;
longitudine = 0;
lat = latitudine;
lon = longitudine;
}
if (status&0x08){
}
else{
gap=gap-1;
}
if (status&0x04){
}
else{
gap=gap-1;
}
battery = bytes_def.slice(index[3]+gap,index[3]+gap+2);
rssi = bytes_def[15];
snr = bytes_def[16];
bat = (battery[0])*256+(battery[1]);
lat=parseFloat(Math.round(lat * 1000000) / 1000000).toFixed(6);
lon=parseFloat(Math.round(lon * 1000000) / 1000000).toFixed(6);
latlon = lat.toString()+’\u0020’+lon.toString()+’\u0020’+bat.toString();
if(status&0x20){
bot = “buttonTransmission”;
}
else{
bot = “periodicTransmission”;
}
//return {“payload”: latlon};

//var ll = {"lat":parseFloat(lat), "lon":parseFloat(lon)};
//return [ll, {"bat":parseInt(bat), "button":bot.toString()}]
return { 
  data:{"object":{"latitude":parseFloat(lat), "longitude":parseFloat(lon)}, "bat":parseInt(bat), "button":bot.toString()}
};

}
if (fport_def==2){
var gps =[];
var battery =[];
var lat =[];
var lon =[];
gps=bytes_def[1]&0xF;
bat=bytes_def[2];
lati=bytes_def.slice(3,7);
long=bytes_def.slice(7,11);
var lat = ((lati[3]>>4)*16+(lati[3]&0xF)+(lati[2]>>4)*4096+(lati[2]&0xF)*256+
(lati[1]>>4)*1048576+(lati[1]&0xF)*65536+(lati[0]>>4)*268435456+(lati[0]&0xF)*16777216)*0.000001;
var lon = ((long[3]>>4)*16+(long[3]&0xF)+(long[2]>>4)*4096+(long[2]&0xF)*256+
(long[1]>>4)*1048576+(long[1]&0xF)*65536+(long[0]>>4)*268435456+(long[0]&0xF)*16777216)*0.000001;
if(status&0x20){
bot = “buttonTransmission”;
}
else{
bot = “periodicTransmission”;
}
return {
data: {“GPS”: gps, “bat”:parseInt(bat),“object”:{“latitude”:parseFloat(lat), “longitude”:parseFloat(lon)}, “button”:bot.toString()}
};
}
}