RAK10701-L payload for datacake is not working

Issue:i need the decoder and the encoder of the device , Im using datacake integration directly from ttn just because i cant download chisptack but in the manual just have tutorial if I use chrisptack , i need help please

do you have the correct decoder from that part

Welcome to RAK forum @roby ,

You can use this decoder in TTN.

function Decoder(bytes, port) {
	var decoded = {};
	// avoid sending Downlink ACK to integration (Cargo)
	if (port === 1) {
		var lonSign = (bytes[0] >> 7) & 0x01 ? -1 : 1;
		var latSign = (bytes[0] >> 6) & 0x01 ? -1 : 1;

		var encLat = ((bytes[0] & 0x3f) << 17) +
			(bytes[1] << 9) +
			(bytes[2] << 1) +
			(bytes[3] >> 7);

		var encLon = ((bytes[3] & 0x7f) << 16) +
			(bytes[4] << 8) +
			bytes[5];

		var hdop = bytes[8] / 10;
		var sats = bytes[9];

		const maxHdop = 2;
		const minSats = 5;

		if ((hdop < maxHdop) && (sats >= minSats)) {
			// Send only acceptable quality of position to mappers
			decoded.latitude = latSign * (encLat * 108 + 53) / 10000000;
			decoded.longitude = lonSign * (encLon * 215 + 107) / 10000000;
			decoded.altitude = ((bytes[6] << 8) + bytes[7]) - 1000;
			decoded.accuracy = (hdop * 5 + 5) / 10
			decoded.hdop = hdop;
			decoded.sats = sats;
		} else {
			decoded.error = "Need more GPS precision (hdop must be <" + maxHdop +
				" & sats must be >= " + minSats + ") current hdop: " + hdop + " & sats:" + sats;
		}
		return decoded;
	}
	return null;
}

yes actually I have that for tnt , but i have this code that i have to put in datacake payload and isn’t not working as well

in the steps of the manual i have to use that

but is not working on datacake

this is the code:

function distance(lat1, lon1, lat2, lon2) {
    if ((lat1 == lat2) && (lon1 == lon2)) {
        return 0;
    }
    else {
        var radlat1 = Math.PI * lat1 / 180;
        var radlat2 = Math.PI * lat2 / 180;
        var theta = lon1 - lon2;
        var radtheta = Math.PI * theta / 180;
        var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
        if (dist > 1) {
            dist = 1;
        }
        dist = Math.acos(dist);
        dist = dist * 180 / Math.PI;
        dist = dist * 60 * 1.1515;
        dist = dist * 1.609344;
        return dist;
    }
}

function Decoder(bytes, fPort) {
    var decoded = {};
    // avoid sending Downlink ACK to integration (Cargo)
    if (fPort === 1) {
        var lonSign = (bytes[0] >> 7) & 0x01 ? -1 : 1;
        var latSign = (bytes[0] >> 6) & 0x01 ? -1 : 1;

        var encLat = ((bytes[0] & 0x3f) << 17) +
            (bytes[1] << 9) +
            (bytes[2] << 1) +
            (bytes[3] >> 7);

        var encLon = ((bytes[3] & 0x7f) << 16) +
            (bytes[4] << 8) +
            bytes[5];

        var hdop = bytes[8] / 10;
        var sats = bytes[9];

        var maxHdop = 2;
        var minSats = 5;

        if ((hdop < maxHdop) && (sats >= minSats)) {
            // Send only acceptable quality of position to mappers
            decoded.latitude = latSign * (encLat * 108 + 53) / 10000000;
            decoded.longitude = lonSign * (encLon * 215 + 107) / 10000000;
            decoded.altitude = ((bytes[6] << 8) + bytes[7]) - 1000;
            decoded.accuracy = (hdop * 5 + 5) / 10
            decoded.hdop = hdop;
            decoded.sats = sats;
            decoded.location = "(" + decoded.latitude + "," + decoded.longitude + ")";
        } else {
            decoded.error = "Need more GPS precision (hdop must be <" + maxHdop +
                " & sats must be >= " + minSats + ") current hdop: " + hdop + " & sats:" + sats;
            decoded.latitude = latSign * (encLat * 108 + 53) / 10000000;
            decoded.longitude = lonSign * (encLon * 215 + 107) / 10000000;
            decoded.altitude = ((bytes[6] << 8) + bytes[7]) - 1000;
            decoded.accuracy = (hdop * 5 + 5) / 10
            decoded.hdop = hdop;
            decoded.sats = sats;
            decoded.location = "(" + decoded.latitude + "," + decoded.longitude + ")";
        }
        //      decoded.raw = rawPayload.uplink_message.rx_metadata[0].location;
        decoded.num_gw = normalizedPayload.gateways.length;
        decoded.minRSSI = 0;
        decoded.maxRSSI = 0;
        decoded.minSNR = 0;
        decoded.maxSNR = 0;
        decoded.minDistance = 0;
        decoded.maxDistance = 0;

        var server_type = 0;
        // Check if payload comes from TTN
        if (typeof (rawPayload.uplink_message) != "undefined") {
            console.log("Found TTN format");
            server_type = 1;
        }
        // Check if payload comes from Helium
        else if (typeof (rawPayload.hotspots) != "undefined") {
            console.log("Found Helium format");
            server_type = 2;
        }
        // Check if payload comes from Chirpstack
        else if (typeof (rawPayload.rxInfo) != "undefined") {
            console.log("Found Chirpstack format");
            server_type = 3;
            decoded.is_chirpstack = 1;
        }
        else {
            console.log("Unknown raw format");
        }

        var gw_lat = {};
        var gw_long = {};

        decoded.num_gw = 0;
        for (idx_tst = 0; idx_tst < 10; idx_tst++)
        {
            if (typeof (normalizedPayload.gateways[idx_tst]) != "undefined")
            {
                console.log("Found gateway with IDX " + idx_tst);
                decoded.num_gw += 1;
            }
        }

        for (idx = 0; idx < decoded.num_gw; idx++) {
            var new_rssi = (!!normalizedPayload.gateways && !!normalizedPayload.gateways[idx] && normalizedPayload.gateways[idx].rssi) || 0;
            var new_snr = (!!normalizedPayload.gateways && !!normalizedPayload.gateways[idx] && normalizedPayload.gateways[idx].snr) || 0;
            if ((new_rssi < decoded.minRSSI) || (decoded.minRSSI == 0)) {
                decoded.minRSSI = new_rssi;
            }
            if ((new_rssi > decoded.maxRSSI) || (decoded.maxRSSI == 0)) {
                decoded.maxRSSI = new_rssi;
            }
            if ((new_snr < decoded.minSNR) || (decoded.minSNR == 0)) {
                decoded.minSNR = new_snr;
            }
            if ((new_snr > decoded.maxSNR) || (decoded.maxSNR == 0)) {
                decoded.maxSNR = new_snr;
            }

            // var gw_lat = 0.0;
            // var gw_long = 0.0;
            switch (server_type) {
                //TTN
                case 1:
                    gw_lat[idx] = rawPayload.uplink_message.rx_metadata[idx].location.latitude;
                    gw_long[idx] = rawPayload.uplink_message.rx_metadata[idx].location.longitude;
                    break;
                // Helium
                case 2:
                    gw_lat[idx] = rawPayload.hotspots[idx].lat;
                    gw_long[idx] = rawPayload.hotspots[idx].long;
                    break;
                // Chirpstack
                case 3:
                    gw_lat[idx] = rawPayload.rxInfo[idx].location.latitude;
                    gw_long[idx] = rawPayload.rxInfo[idx].location.longitude;
                    break;
                default:
                    console.log("Unknown LNS");
                    break;
            }

            console.log("IDX " + idx + " lat " + gw_lat[idx] + " long " + gw_long[idx]);
            // decoded.gw_lat[idx] = gw_lat;
            // decoded.gw_long[idx] = gw_long;

            // Calculate distance
            var new_distance = distance(gw_lat[idx], gw_long[idx], decoded.latitude, decoded.longitude);
            if ((new_distance < decoded.minDistance) || (decoded.minDistance == 0)) {
                decoded.minDistance = new_distance * 1000;
            }
            if ((new_distance > decoded.maxDistance) || (decoded.maxDistance == 0)) {
                decoded.maxDistance = new_distance * 1000;
            }
        }

        switch (decoded.num_gw) {
            case 20:
                decoded.hotspot_10 = "(" + gw_lat[19] + "," + gw_long[19] + ")";
            case 19:
                decoded.hotspot_09 = "(" + gw_lat[18] + "," + gw_long[18] + ")";
            case 18:
                decoded.hotspot_08 = "(" + gw_lat[17] + "," + gw_long[17] + ")";
            case 17:
                decoded.hotspot_07 = "(" + gw_lat[16] + "," + gw_long[16] + ")";
            case 16:
                decoded.hotspot_06 = "(" + gw_lat[15] + "," + gw_long[15] + ")";
            case 15:
                decoded.hotspot_05 = "(" + gw_lat[14] + "," + gw_long[14] + ")";
            case 14:
                decoded.hotspot_04 = "(" + gw_lat[13] + "," + gw_long[13] + ")";
            case 13:
                decoded.hotspot_03 = "(" + gw_lat[12] + "," + gw_long[12] + ")";
            case 12:
                decoded.hotspot_02 = "(" + gw_lat[11] + "," + gw_long[11] + ")";
            case 11:
                decoded.hotspot_01 = "(" + gw_lat[10] + "," + gw_long[10] + ")";
            case 10:
                decoded.hotspot_10 = "(" + gw_lat[9] + "," + gw_long[9] + ")";
            case 9:
                decoded.hotspot_09 = "(" + gw_lat[8] + "," + gw_long[8] + ")";
            case 8:
                decoded.hotspot_08 = "(" + gw_lat[7] + "," + gw_long[7] + ")";
            case 7:
                decoded.hotspot_07 = "(" + gw_lat[6] + "," + gw_long[6] + ")";
            case 6:
                decoded.hotspot_06 = "(" + gw_lat[5] + "," + gw_long[5] + ")";
            case 5:
                decoded.hotspot_05 = "(" + gw_lat[4] + "," + gw_long[4] + ")";
            case 4:
                decoded.hotspot_04 = "(" + gw_lat[3] + "," + gw_long[3] + ")";
            case 3:
                decoded.hotspot_03 = "(" + gw_lat[2] + "," + gw_long[2] + ")";
            case 2:
                decoded.hotspot_02 = "(" + gw_lat[1] + "," + gw_long[1] + ")";
            case 1:
                decoded.hotspot_01 = "(" + gw_lat[0] + "," + gw_long[0] + ")";
            default:
                break;
        }

        decoded.maxMod = parseInt((decoded.maxDistance / 250), 10);
        decoded.minMod = parseInt((decoded.minDistance / 250), 10);
        decoded.maxDistance = parseInt((decoded.maxMod * 250), 10);
        decoded.minDistance = parseInt((decoded.minMod * 250), 10);
        if (decoded.maxDistance <= 1) {
            decoded.maxDistance = parseInt(250, 10);
        }
        if (decoded.minDistance <= 1) {
            decoded.minDistance = parseInt(250, 10);
        }
        return decoded;
    }
    return null;

}







![image|690x381](upload://y8PWRJ5ForGsY5g13qS07Fhxd92.png)

The function names in the decoder are different between TTN and Chirpstack.

For TTN, Helium and Datacake the function call in the decoder is:

// For TTN, Helium and Datacake
function Decoder(bytes, fport) {
}

For Chirpstack it is

// For Chirpstack
function Decode(fPort, bytes, variables) {
}

A possible solution is to change the decoder like this:

// For TTN, Helium and Datacake
function Decoder(bytes, fport) {
   // keep the decoding functions as they are
}
// For Chirpstack
function Decode(fPort, bytes, variables) {
   return Decoder(bytes, fport);
}

si, eso ya lo se pero lo que quiero es el codigo que debo colococar del rak10701-l en datacake porque el que tengo no funciona con todo y que coloque las funciones como me dice que tengo que usarlas , aparte necesito el encoder que va de retorno como downlink a ttn . ya que no sale en ningun lado ese codigo , pero el payload de subida si lo tengo, gracias

I am sorry, I do not understand Spanish and the Google translation doesn’t make much sense.

Yes, I already know that, but what I want is the code that I have to put the rak10701-l in datacake because the one I have doesn't work with everything and to put the functions as it tells me I have to use them, apart from that I need the encoder that goes from return as downlink to ttn . Since that code does not appear anywhere, but I do have the upload payload, thanks

I am using the decoder from our Github repo and it is working fine on Datacake.

thanks man , have a nice valentine day

Hello Mr. Bernd
I have the exact same situation as the colleague above. I use a RAK10701 tester registered in TTS (sandbox), where everything works OK (that short payload decoder works OK). I use Datacake for data visualization. And even there the proposed Payload Decoder, which I took from GitHub, works with one very important error (at least for me). When RAK10701 detects more than two gateways, the Payload decoder reports an error: Code error: threw error: TypeError: Cannot access member ‘latitude’ of undefined and no longer displays the data. Can someone help me unravel the problem or tell me what is wrong in my case. Best regards, Tomo

Welcome to the forum @Tomo

Did you try the decoder from the Github link?
I will have to check what I have right now on Datacake, but I tested it with 3 gateways and it didn’t throw errors.
However, the new RAK10701 firmware has some extensions. Not sure if that is covered by the payload decoder already.

Hi Bernd…
Yes, I’m using exactly that Payload decoder from Git Hub link.
It works for 1 or 2 Gateways for sure. When the tester sees 3,4,5 Gateways, it reports an error.
I even managed to decode the data for 6 Gateways, but I don’t know with which version of the Payload decoder, because it was a lot of blind testing before I linked the error to the number of Gateways. I collected various payload decoders from the Datacake database, from the RAK documentation,…
I would be very happy if you could find out where the error is, because we often have environments with several Gateways. For visualization, we use Datacake and data directly from it TTS - SANDBOX.
Best regards, Tomo

Another picture with successful decoding of 6 gateways…

Best regards, Tomo

I am not sure what the problem is.
I tested again with 3 gateways with Chirpstack and it is working fine.
So I guess the problem must be within the fact that you are using TTI.

Can you give me the content of the webhook received from TTI (if possible as text, not as screenshot):

Btw, if you are using TTN/TTI, why do you not use the “native” integration RAK10701-P Field Tester Pro Guide for The Things Network?

Payload

"root":**{**

*4 items*

"end_device_ids":**{**

*5 items*

"device_id":

string"eui-ac1f09fffe0cf334"

"application_ids":**{**

*1 item*

"application_id":

string"x-xxxxtester"

**}**

"dev_eui":

string"AC1F09FFFE0CF334"

"join_eui":

string"AC1F0xxxF8680701"

"dev_addr":

string"260B0E2B"

**}**

"correlation_ids":**[**

*1 item*

0

:

string"gs:uplink:01HQT5SHJQ61EGS1DHDVCJ2D9M"

**]**

"received_at":

string"2024-02-29T10:15:37.523088186Z"

"uplink_message":**{**

*12 items*

"session_key_id":

string"AY30VTxxxTka4+CZuqu2Zg=="

"f_port":

int1

"f_cnt":

int7

"frm_payload":

string"IG+9iaqFBFoNCw=="

"decoded_payload":**{**

*6 items*

"accuracy":

float1.15

"altitude":

int114

"hdop":

float1.3

"latitude":

float45.9163673

"longitude":

float13.6197662

"sats":

int11

**}**

"rx_metadata":**[**

*5 items*

0:**{**

*8 items*

"gateway_ids":**{**

*2 items*

"gateway_id":

string"san-floriano-del-collio"

"eui":

string"C0EE40FFFF296845"

**}**

"timestamp":

int492264100

"rssi":

int-111

"channel_rssi":

int-111

"snr":

float4.8

"uplink_token":

string"CiUKIwoXc2FuLWZsb3JpYW5vLWRlbC1jb2xsaW8SCMDuQP//KWhFEKS13eoBGgwIybKBrwYQ5p3XkAEgoKHo6anYEQ=="

"channel_index":

int3

"received_at":

string"2024-02-29T10:15:37.279754341Z"

**}**

1:**{**

*9 items*

"gateway_ids":**{**

*2 items*

"gateway_id":

string"xiris-gw-5292-01"

"eui":

string"24E124FFFEF4761A"

**}**

"time":

string"2024-02-29T10:15:37.245135068Z"

"timestamp":

float3951399705

"rssi":

int-122

"channel_rssi":

int-122

"snr":

int-4

"location":**{**

*4 items*

"latitude":

float45.8720192861716

"longitude":

float13.6568936705589

"altitude":

int208

"source":

string"SOURCE_REGISTRY"

**}**

"uplink_token":

string"Ch4KHAoQeGlyaXMtZ3ctNTI5Mi0wMRIIJOEk//70dhoQmaaW3A4aDAjJsoGvBhDJgPeSASCos5qOgMAR"

"received_at":

string"2024-02-29T10:15:37.284598634Z"

**}**

2:**{**

*9 items*

"gateway_ids":**{**

*2 items*

"gateway_id":

string"xiris-gw-5290-01"

"eui":

string"B827EBFFFE1F43CC"

**}**

"time":

string"2024-02-29T10:15:36.065701961Z"

"timestamp":

float3985017676

"rssi":

int-46

"channel_rssi":

int-46

"snr":

float9.5

"location":**{**

*4 items*

"latitude":

float45.916388872042916

"longitude":

float13.619886492385595

"altitude":

int60

"source":

string"SOURCE_REGISTRY"

**}**

"uplink_token":

string"Ch4KHAoQeGlyaXMtZ3ctNTI5MC0wMRIIuCfr//4fQ8wQzJaa7A4aDAjJsoGvBhC4oKWUASDgwcCs/cAR"

"received_at":

string"2024-02-29T10:15:37.289082311Z"

**}**

3:**{**

*9 items*

"gateway_ids":**{**

*2 items*

"gateway_id":

string"xiris-gw-5293-01"

"eui":

string"24E124FFFEF47588"

**}**

"time":

string"2024-02-29T10:15:37.246973037Z"

"timestamp":

float3959256077

"rssi":

int-134

"channel_rssi":

int-134

"snr":

int-14

"location":**{**

*4 items*

"latitude":

float45.906265

"longitude":

float13.699533

"altitude":

int110

"source":

string"SOURCE_REGISTRY"

**}**

"uplink_token":

string"Ch4KHAoQeGlyaXMtZ3ctNTI5My0wMRIIJOEk//70dYgQjej13w4aDAjJsoGvBhC2oqqUASDIpbWwncAR"

"received_at":

string"2024-02-29T10:15:37.284852113Z"

**}**

4:**{**

*9 items*

"gateway_ids":**{**

*2 items*

"gateway_id":

string"75-gw-5000-01"

"eui":

string"B827EBFFFED3C6EE"

**}**

"time":

string"2024-02-29T10:15:37.252624034Z"

"timestamp":

float3983704604

"rssi":

int-120

"channel_rssi":

int-120

"snr":

float-16.75

"location":**{**

*4 items*

"latitude":

float45.94244009091676

"longitude":

float13.64093989133835

"altitude":

int80

"source":

string"SOURCE_REGISTRY"

**}**

"uplink_token":

string"ChsKGQoNNzUtZ3ctNTAwMC0wMRIIuCfr//7Txu4QnITK6w4aDAjJsoGvBhCnm7ybASDg+rC6+MAR"

"received_at":

string"2024-02-29T10:15:37.295647268Z"

**}**

**]**

"settings":**{**

*3 items*

"data_rate":**{**

*1 item*

"lora":**{**

*3 items*

"bandwidth":

int125000

"spreading_factor":

int10

"coding_rate":

string"4/5"

**}**

**}**

"frequency":

string"867100000"

"timestamp":

int492264100

**}**

"received_at":

string"2024-02-29T10:15:37.304076006Z"

"confirmed":

booltrue

"consumed_airtime":

string"0.370688s"

"locations":**{**

*1 item*

"frm-payload":**{**

*5 items*

"latitude":

float45.9163673

"longitude":

float13.6197662

"altitude":

int114

"accuracy":

int1

"source":

string"SOURCE_GPS"

**}**

**}**

"network_ids":**{**

*5 items*

"net_id":

string"000013"

"ns_id":

string"EC656E0000000181"

"tenant_id":

string"ttn"

"cluster_id":

string"eu1"

"cluster_address":

string"eu1.cloud.thethings.network"

**}**

**}**

**}**

I think I found it.
The first gateway does not have location information, which causes the decoder to fail.

			"0": {
				"gateway_ids": {
					"gateway_id": "san-floriano-del-collio",
					"eui": "C0EE40FFFF296845"
				},
				"timestamp": 492264100,
				"rssi": -111,
				"channel_rssi": -111,
				"snr": 4.8,
				"uplink_token": "CiUKIwoXc2FuLWZsb3JpYW5vLWRlbC1jb2xsaW8SCMDuQP//KWhFEKS13eoBGgwIybKBrwYQ5p3XkAEgoKHo6anYEQ==",
				"channel_index": 3,
				"received_at": "2024-02-29T10:15:37.279754341Z"
			},

Others have the location information

			"1": {
				"gateway_ids": {
					"gateway_id": "xiris-gw-5292-01",
					"eui": "24E124FFFEF4761A"
				},
				"time": "2024-02-29T10:15:37.245135068Z",
				"timestamp": 3951399705,
				"rssi": -122,
				"channel_rssi": -122,
				"snr": -4,
				"location": {
					"latitude": 45.8720192861716,
					"longitude": 13.6568936705589,
					"altitude": 208,
					"source": "SOURCE_REGISTRY"
				},
				"uplink_token": "Ch4KHAoQeGlyaXMtZ3ctNTI5Mi0wMRIIJOEk//70dhoQmaaW3A4aDAjJsoGvBhDJgPeSASCos5qOgMAR",
				"received_at": "2024-02-29T10:15:37.284598634Z"
			},

Can you try the attached updated decoder, I cannot really test, all my gateways have location info.

test-decoder.zip (1.8 KB)

Another workaround would be to make sure all gateways report a location or have a “fake” location assigned in TTN in the gateway settings.