How to send CayenneLPP using library SX126x-Arduino

Please include the following information, in order for us to help you as effectively as possible.

  • What product do you wish to discuss? RAK4631, RAK3372, RAK11200, RAK11310, RAK11722?

  • What firmware are you using? VSCode/PlatformIO

  • What firmware version?

  • Computer OS? (MacOS, Linux, Windows) Windows

  • What Computer OS version? Windows 11

  • How often does the problem happen? it is not a problem

  • How can we replicate the problem? yes I can replicate

  • Provide source code if custom firmware is used or link to example if RAKwireless example code is used.

Good morning,

I am using CayenneLPP to pack the sensors(RAK1904, RAK1906, RAK5801 and RAK12500) values read and library SX126x-Arduino to send the LPP package to LoRa Server.

I am using “Radio.Send”(from Radio.h in teh SX126x folder) but it is not working as I was expecting, I mean the LPP package is not being sent.

Could you help me to find the correct function and the way to send the LPP package?

Regards,

Claudio

PackPayload.h


#include <Arduino.h>
#include <CayenneLPP.h>
#include <SX126x-Arduino.h>

float celsius   = -4.1;
float accel[]   = {1.234, -1.234, 0};
float rh        = 30;
float hpa       = 1014.1;
float latitude  = 42.3519;
float longitude = -87.9094;
float altitude  = 10;

// Low Power Payload object - LPP
CayenneLPP LPP(MAX_SIZE);

uint8_t size = 0;

extern struct Acel
{
    public:
    float EixoX;
    float EixoY;
    float EixoZ;
    float Movimento[3];
} RAK1904;

extern struct Ambiental
{
    public:
    float Temperatura   = 0;
    float PressAtm      = 0;
    float Humidade      = 0;
    float ResistenciaAr = 0;
} RAK1906;

extern struct GeoLocalizacao
{
    public:
    float Latitude      = 0;    // latitude em graus
    float Longitude     = 0;    // Longitude em graus
    float Altitude      = 0;    // Altitude em metros
    float Acuracia      = 0;    // índice de precisão
    float HDop          = 0;    // dispersão horizontal
    float Velocidade    = 0;    // Velocidade em m/s
    float Direcao       = 0;    // Direção em graus
    uint8_t sats        = 0;    // número de satélites

} RAK12500;

void Empacota();

extern void LoRaEnvia();

PackPayload.cpp

#include <PackPayload.h>



void Empacota()
{

    LPP.reset();

    size = LPP.addTemperature(0, celsius);

    if (size == 0) {
        // not enough byte left to add the data
    }

    else {
        // add function returned current payload size
    }


    LPP.addAccelerometer(113,RAK1904.EixoX,RAK1904.EixoY,RAK1904.EixoZ);
    LPP.addTemperature(7, RAK1906.Temperatura);
    LPP.addRelativeHumidity(6, RAK1906.Humidade);
    LPP.addBarometricPressure(8, RAK1906.PressAtm);
    LPP.addGPS(10, RAK12500.Latitude, RAK12500.Longitude, RAK12500.Altitude);
   	    // Call LoRaWAN library to send the frame
    Radio.Send(LPP.getBuffer(), LPP.getSize());
} 

What value is_MAX_SIZE_ ? Maximum allowed by the CayenneLPP library is 255.
Do a LPP.reset() before you add the values.

Good night :slight_smile:

In my LoRa Certification course, I got a resume of LoRa parameters that I paste below. Please correct me if I am wrong, but as payload size could be between 51 and 222, I selected the worst case(SF=10), I mean MAX_SIZE = 51. I think that in my case it will be enough, because the sum of sensors value should be less than 20 bytes.

Is it correct?

LPP.reset() is the first execution in this function.

Cláudio

Hi @beegee ,

I did a improvement in the code to receive a better debug. Sorry because the printed message are in portuguese because my client is a Brazilian company :slight_smile:

Below I attached the new code version, the monitor serial output and the last, a TTN endnode log:

The sizing test show that the buffer size has the right size, I mean 30 and the MAX_SIZE is 50: ============= Payload de 30 cabe no buffer de 51

Well as you can see the endnode log in the TTN Server, I can see the join, but I can´t see the payload reaching the TTN

#include <PackPayload.h>



void Empacota()
{

	Serial.println("=======================================================");
    Serial.println("============= Iniciando o empacotamento ===============");

    LPP.reset();

    LPP.addAccelerometer(113,RAK1904.EixoX,RAK1904.EixoY,RAK1904.EixoZ);
    LPP.addTemperature(7, RAK1906.Temperatura);
    LPP.addRelativeHumidity(6, RAK1906.Humidade);
    LPP.addBarometricPressure(8, RAK1906.PressAtm);
    LPP.addGPS(10, RAK12500.Latitude, RAK12500.Longitude, RAK12500.Altitude);

    size = LPP.getSize();

    if (size > MAX_SIZE) {
        Serial.printf("============= Payload de %u\n", size);
        Serial.printf(" não cabe no buffer de %d\n, MAX_SIZE", MAX_SIZE);
        Serial.println(" ==== ERRO - Aumente o tamnho do buffer para que o Payload resultante possa ser transmitido ===");
            
    } else {
        Serial.printf("============= Payload de %u", size);
        Serial.printf(" cabe no buffer de %d\n", MAX_SIZE);
        Serial.println(" ==== SUCESSO - o payload pode ser transmitido via LoRa ===");
        }
   	    // Call LoRaWAN library to send the frame
    Radio.Send(LPP.getBuffer(), LPP.getSize());

Monitor Serial Output

--- Terminal on COM8 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
INICIOU A PORTA SERIAL
=====================================
Bem vindo LoRa do RAK4630 !!!
=====================================
sucesso ao inciar o LoRa - código =  0
=====================================
= Tentativa 0 de conexão à Rede LoRa ==
========= Erro 2
= Tentativa 1 de conexão à Rede LoRa ==
========= Erro 2
= Tentativa 2 de conexão à Rede LoRa ==
========= Erro 2
= Tentativa 3 de conexão à Rede LoRa ==
========= Erro 2
= Tentativa 4 de conexão à Rede LoRa ==
========= Erro 2
= Tentativa 5 de conexão à Rede LoRa ==
========= Erro 2
= Conexão na Rede LoRa feita no modo OTAA, com sucesso =
========================================================
============  Iniciando o RAK12500 via I2C ============
=======================================================
=========== RA12500 inciado com sucesso ===============
=======================================================
= RAK1904 iniciado na I2C no endereço 0x18, com sucesso
=======================================================
======== RAK5801 iniciado na porta WB_I01 =============
=======================================================

=======================================================
============= Saida no Monitor 1 ====================
============== Quantidade de Movimento ===============
 X(g) = -0.8487 mG
 Y(g) = 0.0000 mG
 Z(g)= -0.4644 mG
=============== Variáveis Ambientais ==================
=======================================================
Temperatura = 30.27 *C
Pressão Atmosférica = 1017.77 hPa
Humidade = 0.00 %
Resistência do Gas = 8.28 KOhms

=======================================================
============= Geo-localização =========================
 Lat: 0.00
 Long: 0.00 (graus * 10^-7)
 Alt: 0.00 (M)
 Acuracia: 10272833536.00 (%)
 Velocidade: 0.00 (M/s)
 Direção: 0.00 (graus * 10^-5)
 Satélites: 0
=======================================================
========== Pressão Pneumatica      =====================
-------ValorMedioLidoTransd------ = 0
-------voltage_ain------ = 0.000000
-------current_sensor------ = 0.000000
-------Pressao Calculada ------ = 0.000000  KPa
-------Pressao Calculada ------ = 0.000000  psi
=======================================================
============= Iniciando o empacotamento ===============
============= Payload de 30 cabe no buffer de 51
 ==== SUCESSO - o payload pode ser transmitido via LoRa ===
Enviando pacote agora...
lmh_send ok contador 1
Enviando pacote agora...
lmh_send ok contador 2

TTN endnode log

Radio.Send is for LoRa P2P. You should use lmh_send

Example:

/** LoRaWAN application data buffer. */
static uint8_t m_lora_app_data_buffer[256];
/** Lora application data structure. */
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0};

lmh_error_status send_lora_packet(uint8_t *data, uint8_t size, uint8_t fport)
{
	if (lmh_join_status_get() != LMH_SET)
	{
		// Not joined, try again later
		Serial.println("Did not join network, skip sending frame");
		return LMH_ERROR;
	}

	if (fport != 0)
	{
		m_lora_app_data.port = fport;
	}
	else
	{
		m_lora_app_data.port = g_lorawan_settings.app_port;
	}

	m_lora_app_data.buffsize = size;

	memcpy(m_lora_app_data_buffer, data, size);

	return lmh_send(&m_lora_app_data, g_lorawan_settings.confirmed_msg_enabled);
}

How could I send the LPP payload with lmh_send ? I mean, I didn´t find a documentation how lmh_send works.

Could it be “lmh_send(&LPP, LPP.getSize())”? Could it be like a example code below?

#include <SPI.h>
#include "LoRa.h" // Assuming LoRa.h includes SX126x-Arduino.h internally

#define BAND    915E6  // LoRa frequency for US915 band

void setup() {
  Serial.begin(9600);
  while (!Serial);

  LoRa loraModule; // Create an instance of LoRa object

  // Initialize LoRa module
  if (!loraModule.begin(BAND)) {
    Serial.println("LoRa initialization failed!");
    while (1);
  }
}

void loop() {
  LoRa loraModule; // Create an instance of LoRa object

  // Create CayenneLPP payload
  CayenneLPP lpp(50); // Initialize CayenneLPP object with buffer size
  
  // Add data to CayenneLPP payload
  lpp.addTemperature(1, 25.5); // Add temperature data (channel 1)
  lpp.addAnalogInput(2, 123); // Add analog input data (channel 2)
  // You can add more sensor data as needed
  
  // Send CayenneLPP packet
  if (loraModule.lmh_send(lpp.getBuffer(), lpp.getSize())) {
    Serial.println("CayenneLPP packet sent successfully!");
  } else {
    Serial.println("Failed to send CayenneLPP packet!");
  }
  
  delay(10000); // Delay before sending the next packet (10 seconds)
}

If you kept the same lmh_send() function parameters) it expects the data in a structure:

/**@brief Application Data structure
 */
typedef struct
{
	uint8_t *buffer;  /**< point to the LoRa App data buffer */
	uint8_t buffsize; /**< LoRa App data buffer size */
	uint8_t port;	  /**< Port on which the LoRa App is data is sent/ received */
	int16_t rssi;	  /**< RSSI of received packet */
	uint8_t snr;	  /**< SNR of received packet */
} lmh_app_data_t;

So you have to fill this structure and give it to the lmh_send function.

// .....

/** LoRaWAN application data buffer. */
static uint8_t m_lora_app_data_buffer[256];
/** Lora application data structure. */
static lmh_app_data_t m_lora_app_data = {m_lora_app_data_buffer, 0, 0, 0, 0};

// Create CayenneLPP payload
CayenneLPP lpp(50); // Initialize CayenneLPP object with buffer size

// .....

void loop()
{
	// Reset the payload buffer
	lpp.reset();

	// Add data to CayenneLPP payload
	lpp.addTemperature(1, 25.5); // Add temperature data (channel 1)
	lpp.addAnalogInput(2, 123);	 // Add analog input data (channel 2)

	// Set the fPort
	m_lora_app_data.port = fport; // Choose the fPort you want to use
	// Set the size of the payload
	m_lora_app_data.buffsize = lpp.getSize();
	// Copy the payload into the structure
	memcpy(m_lora_app_data_buffer, lpp.getBuffer(), lpp.getSize());

	// Send packet
	if (LoRa.lmh_send(&m_lora_app_data))
	{
		Serial.println("Packet sent successfully!");
	}
	else
	{
		Serial.println("Failed to send packet!");
	}

	delay(1000); // Delay before sending the next packet
}

Thank you, I will test it and as soon as possible, I will send news about it.

Now the code is working fine. Now I am working to clean the code to deliver the first version.

In the next steps I am planning to become it Low Power WAN :slight_smile:

Thank you very much again!

Cláudio

void LoRaEnvia()
{
 	// Set the fPort
	PayloadEstrutura.port = LoRaAplicPorta; // Choose the fPort you want to use
	// Set the size of the payload
	PayloadEstrutura.buffsize = LPP.getSize();
	// Copy the payload into the structure
	memcpy(PayloadBufferTam, LPP.getBuffer(), LPP.getSize());


    lmh_error_status error = lmh_send(&PayloadEstrutura, LoRaEnvioConfirmado);
	if (error == LMH_SUCCESS)
	{
		g_count++;
		Serial.printf("lmh_send ok contador %d\n", g_count);
	}
	else
	{
		g_count_fail++;
		Serial.printf("lmh_send falhou contador %d\n", g_count_fail);
	}
}

TTN Server meta-data

{
  "name": "as.up.data.forward",
  "time": "2024-04-09T15:39:15.531366259Z",
  "identifiers": [
    {
      "device_ids": {
        "device_id": "mgbhpre001",
        "application_ids": {
          "application_id": "pnem-freio-trem"
        },
        "dev_eui": "AC1F09FFFE0CF041",
        "join_eui": "AC1F09FF00000002",
        "dev_addr": "260BB8D0"
      }
    }
  ],
  "data": {
    "@type": "type.googleapis.com/ttn.lorawan.v3.ApplicationUp",
    "end_device_ids": {
      "device_id": "mgbhpre001",
      "application_ids": {
        "application_id": "pnem-freio-trem"
      },
      "dev_eui": "AC1F09FFFE0CF041",
      "join_eui": "AC1F09FF00000002",
      "dev_addr": "260BB8D0"
    },
    "correlation_ids": [
      "gs:uplink:01HV1R6WFP1HXT23PYE93TQSVC"
    ],
    "received_at": "2024-04-09T15:39:15.529147043Z",
    "uplink_message": {
      "session_key_id": "AY7DdggNI8qBbJdYJqXL2g==",
      "f_port": 2,
      "f_cnt": 19,
      "frm_payload": "cXEAQP/Q/DBnZwFdaGh3c3MnkomI/KSg+XBQAAg0",
      "decoded_payload": {
        "accelerometer_113": {
          "x": 0.064,
          "y": -0.048,
          "z": -0.976
        },
        "barometric_pressure_115": 1013,
        "gps_137": {
          "altitude": 21,
          "latitude": -22,
          "longitude": -43
        },
        "relative_humidity_104": 59.5,
        "temperature_103": 34.9
      },
      "rx_metadata": [
        {
          "gateway_ids": {
            "gateway_id": "mgjfgw0002",
            "eui": "7076FF00540401C9"
          },
          "time": "2024-04-09T15:39:15.181Z",
          "timestamp": 1782730003,
          "rssi": -28,
          "channel_rssi": -28,
          "snr": 8,
          "uplink_token": "ChgKFgoKbWdqZmd3MDAwMhIIcHb/AFQEAckQk5qJ0gYaDAijwtWwBhDd8M+XASC4pPSX8ZgJKgsIo8LVsAYQwK6nVg==",
          "channel_index": 2,
          "gps_time": "2024-04-09T15:39:15.181Z",
          "received_at": "2024-04-09T15:39:13.041577524Z"
        }
      ],
      "settings": {
        "data_rate": {
          "lora": {
            "bandwidth": 125000,
            "spreading_factor": 7,
            "coding_rate": "4/5"
          }
        },
        "frequency": "915600000",
        "timestamp": 1782730003,
        "time": "2024-04-09T15:39:15.181Z"
      },
      "received_at": "2024-04-09T15:39:15.320339167Z",
      "consumed_airtime": "0.087296s",
      "locations": {
        "frm-payload": {
          "latitude": -22,
          "longitude": -43,
          "altitude": 21,
          "source": "SOURCE_GPS"
        }
      },
      "network_ids": {
        "net_id": "000013",
        "ns_id": "EC656E0000000181",
        "tenant_id": "ttn",
        "cluster_id": "eu1",
        "cluster_address": "eu1.cloud.thethings.network"
      }
    }
  },
  "correlation_ids": [
    "gs:uplink:01HV1R6WFP1HXT23PYE93TQSVC"
  ],
  "origin": "ip-10-100-13-20.eu-west-1.compute.internal",
  "context": {
    "tenant-id": "CgN0dG4="
  },
  "visibility": {
    "rights": [
      "RIGHT_APPLICATION_TRAFFIC_READ"
    ]
  },
  "unique_id": "01HV1R6WPBRMGRDDCRB3WBYW2N"
}

Good night,

Most of sensors (RAK1904 and RAK1906) data are being encoded and decoded without problems. But RAK12500 latitude, longitude and altitude, using channel 136 or 137 (high precision GPS) aren´t being decoded correctly.

=======================================================
============= Geo-localização =========================
 tamanho de Lat: 4
 tamanho de Long: 4
 tamanho de Long: 2
Inteiros Lat: -229977819 Lon: -433881199
Inteira Alt: 24341 M
Lat: -22.997782 Lon: -43.388120 Alt: 24.34 M
 Acuracia: 0.00 %
 Velocidade:  0.0 m/s
 Direção:  0.0 graus
 Satélites:   8
=======================================================

I found some examples using the variable types definitions with long, other with int64_t and in the CayenneLPP library, they are received by addGPS function as float, but inside, they are converted to int32_t. But I didn´t find a documentation describing what should be the correct type, but I believe that I should follow the Cayenne library, I mean, float.

Well, I believe that I have problems in the Cayenne library.

Could you help me?


uint8_t CayenneLPP::addGPS(uint8_t channel, float latitude, float longitude, float altitude) {
  
  // check buffer overflow
  if ((_cursor + LPP_GPS_SIZE + 2) > _maxsize) {
    _error = LPP_ERROR_OVERFLOW;
    return 0;
  }

  int32_t lat = latitude * LPP_GPS_LAT_LON_MULT;
  int32_t lon = longitude * LPP_GPS_LAT_LON_MULT;
  int32_t alt = altitude * LPP_GPS_ALT_MULT;

  _buffer[_cursor++] = channel;
  _buffer[_cursor++] = LPP_GPS;
  _buffer[_cursor++] = lat >> 16;
  _buffer[_cursor++] = lat >> 8;
  _buffer[_cursor++] = lat;
  _buffer[_cursor++] = lon >> 16;
  _buffer[_cursor++] = lon >> 8;
  _buffer[_cursor++] = lon;
  _buffer[_cursor++] = alt >> 16;
  _buffer[_cursor++] = alt >> 8;
  _buffer[_cursor++] = alt;

  return _cursor;

}

I was struggling with this as well including using uint32 values, which led to wrong coordinates depending on the location.

At the end, I was writing a class extension to the CayenneLPP library, because with WisBlock, I added more value types to the definition.

wisblock_cayenne.h adds some functions, including higher precision location

	uint8_t addGNSS_4(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude); // 4 digit precision
	uint8_t addGNSS_6(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude); // 6 digit precision
	uint8_t addGNSS_H(int32_t latitude, int32_t longitude, int16_t altitude, int16_t accuracy, int16_t battery); // Helium mapper format
	uint8_t addGNSS_T(int32_t latitude, int32_t longitude, int16_t altitude, float accuracy, int8_t sats); // Field Tester format
	uint8_t addVoc_index(uint8_t channel, uint32_t voc_index); // VOC sensor
	uint8_t addSH_2_value(uint8_t channel, uint8_t data_type, float value); // Any sensor not available
	uint8_t addDevID(uint8_t channel, uint8_t *dev_id); // Device ID (used for some special projects of mine)

The functions are in wisblock_cayenne.cpp
For the 4 digit precision it is

/** 32bit value union */
union long_union_s
{
	int32_t val32;
	int8_t val8[4];
};

uint8_t WisCayenne::addGNSS_4(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude)
{
	// check buffer overflow
	if ((_cursor + LPP_GPS4_SIZE + 2) > _maxsize)
	{
		_error = LPP_ERROR_OVERFLOW;
		return 0;
	}
	_buffer[_cursor++] = channel;
	_buffer[_cursor++] = LPP_GPS4;

	long_union_s pos_union;

	// Save default Cayenne LPP precision
	pos_union.val32 = latitude / 1000; // Cayenne LPP 0.0001 ° Signed MSB
	_buffer[_cursor++] = pos_union.val8[2];
	_buffer[_cursor++] = pos_union.val8[1];
	_buffer[_cursor++] = pos_union.val8[0];

	pos_union.val32 = longitude / 1000; // Cayenne LPP 0.0001 ° Signed MSB
	_buffer[_cursor++] = pos_union.val8[2];
	_buffer[_cursor++] = pos_union.val8[1];
	_buffer[_cursor++] = pos_union.val8[0];

	pos_union.val32 = altitude / 10; // Cayenne LPP 0.01 meter Signed MSB
	_buffer[_cursor++] = pos_union.val8[2];
	_buffer[_cursor++] = pos_union.val8[1];
	_buffer[_cursor++] = pos_union.val8[0];

	return _cursor;
}

Hope that helps.

I studied your library and I suppose that it should be applied together with CayenneLPP, because it has only GPS implementation. Am I write?

In the class WisCayenne, you are declaring “public CayenneLPP”. Is it a reference CayenneLPP in the CayenneLPP.h?

I am having problems to make them work together.

Could you help me?

Claudio

class WisCayenne : public CayenneLPP
{
public:
	WisCayenne(uint8_t size) : CayenneLPP(size) {}

	uint8_t addGNSS_4(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude);
	uint8_t addGNSS_6(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude);
	uint8_t addGNSS_H(int32_t latitude, int32_t longitude, int16_t altitude, int16_t accuracy, int16_t battery);
	uint8_t addGNSS_T(int32_t latitude, int32_t longitude, int16_t altitude, float accuracy, int8_t sats);
	uint8_t addVoc_index(uint8_t channel, uint32_t voc_index);
	uint8_t addSH_2_value(uint8_t channel, uint8_t data_type, float value);
	uint8_t addDevID(uint8_t channel, uint8_t *dev_id);

private:
};
class CayenneLPP {

public:

  CayenneLPP(uint8_t size);
  ~CayenneLPP();

  void reset(void);
  uint8_t getSize(void);
  uint8_t *getBuffer(void);
  uint8_t copy(uint8_t *buffer);
  uint8_t getError();

  // Decoder methods
  const char * getTypeName(uint8_t type);
  uint8_t decode(uint8_t *buffer, uint8_t size, JsonArray& root);
  uint8_t decodeTTN(uint8_t *buffer, uint8_t size, JsonObject& root);

  // Original LPPv1 data types
  uint8_t addDigitalInput(uint8_t channel, uint32_t value);
  uint8_t addDigitalOutput(uint8_t channel, uint32_t value);
  uint8_t addAnalogInput(uint8_t channel, float value);
  uint8_t addAnalogOutput(uint8_t channel, float value);
  uint8_t addLuminosity(uint8_t channel, uint32_t value);
  uint8_t addPresence(uint8_t channel, uint32_t value);
  uint8_t addTemperature(uint8_t channel, float value);
  uint8_t addRelativeHumidity(uint8_t channel, float value);
  uint8_t addAccelerometer(uint8_t channel, float x, float y, float z);
  uint8_t addBarometricPressure(uint8_t channel, float value);
  uint8_t addGyrometer(uint8_t channel, float x, float y, float z);
  uint8_t addGPS(uint8_t channel, float latitude, float longitude, float altitude);

  // Additional data types
  uint8_t addUnixTime(uint8_t channel, uint32_t value);
  uint8_t addGenericSensor(uint8_t channel, float value);
  uint8_t addVoltage(uint8_t channel, float value);
  uint8_t addCurrent(uint8_t channel, float value);
  uint8_t addFrequency(uint8_t channel, uint32_t value);
  uint8_t addPercentage(uint8_t channel, uint32_t value);
  uint8_t addAltitude(uint8_t channel, float value);
  uint8_t addPower(uint8_t channel, uint32_t value);
  uint8_t addDistance(uint8_t channel, float value);
  uint8_t addEnergy(uint8_t channel, float value);
  uint8_t addDirection(uint8_t channel, float value);
  uint8_t addSwitch(uint8_t channel, uint32_t value);
  uint8_t addConcentration(uint8_t channel, uint32_t value);
  uint8_t addColour(uint8_t channel, uint8_t r, uint8_t g, uint8_t b);

protected:

  bool isType(uint8_t type);
  uint8_t getTypeSize(uint8_t type);
  uint32_t getTypeMultiplier(uint8_t type);
  bool getTypeSigned(uint8_t type);

  float getValue(uint8_t * buffer, uint8_t size, uint32_t multiplier, bool is_signed);
  uint32_t getValue32(uint8_t * buffer, uint8_t size);
  template <typename T> uint8_t addField(uint8_t type, uint8_t channel, T value);

  uint8_t * _buffer;
  uint8_t _maxsize;
  uint8_t _cursor;
  uint8_t _error = LPP_ERROR_OK;

};

class WisCayenne : public CayenneLPP
{
public:
	WisCayenne(uint8_t size) : CayenneLPP(size) {}

	uint8_t addGNSS_4(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude);
	uint8_t addGNSS_6(uint8_t channel, int32_t latitude, int32_t longitude, int32_t altitude);
	uint8_t addGNSS_H(int32_t latitude, int32_t longitude, int16_t altitude, int16_t accuracy, int16_t battery);
	uint8_t addGNSS_T(int32_t latitude, int32_t longitude, int16_t altitude, float accuracy, int8_t sats);
	uint8_t addVoc_index(uint8_t channel, uint32_t voc_index);
	uint8_t addSH_2_value(uint8_t channel, uint8_t data_type, float value);
	uint8_t addDevID(uint8_t channel, uint8_t *dev_id);

private:
};

WisCayenne is extending the class CayenneLPP, so you need the CayenneLPP library to make it work.

On Arduino BSP this works without problems.

Just have CayenneLPP library installed and include wisblock_cayenne.h in your code.

Thank you. I will try tomorrow morning. I will sleep now…

Have a good day.

Good news! :slight_smile:

We got the right result with your wisblock_cayenne library! I am very happy! Four months of hard work!

Thank you very much by your excellent support! Congratulations by your job!

Now I will begin to build a data dictionary to document and standardize wisblock sensors variables.

Have a nice weekend!

Cláudio

#include <Arduino.h>
#include <CayenneLPP.h>
#include <wisblock_cayenne.h>
// LoRa SX126X RAK4631
#include <SX126x-Arduino.h>
#include <LoRaWan-RAK4630.h> //http://librarymanager/All#SX126x
#include <SX126x-Arduino.h>

#ifndef _TINYUSB_H
#define _TINYUSB_H
#include "Adafruit_TinyUSB.h"
#endif
/*
float celsius   = -4.1;
float accel[]   = {1.234, -1.234, 0};
float rh        = 30;
float hpa       = 1014.1;
float latitude  = 42.3519;
float longitude = -87.9094;
float altitude  = 10;
*/


uint8_t size = 0;
// extern uint8_t size;

// Low Power Payload object - LPP
// CayenneLPP LPP(MAX_SIZE);
// WisCayenne WisCayenneLPP(size);
// CayenneLPP Extention for Wisblock

extern struct Acel
{
    public:
    float EixoX;
    float EixoY;
    float EixoZ;
    float Movimento[3];
} RAK1904;

extern struct Ambiental
{
    public:
    float Temperatura;
    float PressAtm;
    float Humidade;
    float ResistenciaAr;
} RAK1906;

extern struct GeoLocalizacao
{
    public:
    long Latitude;   // latitude em graus
    long Longitude;  // Longitude em graus
    int16_t Altitude;   // Altitude em metros
    int32_t Acuracia;   // índice de precisão
    int16_t HDop;       // dispersão horizontal
    int32_t Velocidade; // Velocidade em m/s
    int32_t Direcao;    // Direção em graus
    byte sats;          // número de satélites

} RAK12500;

// CayenneLPP LPP(MAX_SIZE);
WisCayenne  WisCayenneLPP(MAX_SIZE);

/*
extern lmh_confirm LoRaEnvioConfirmado;
//  LoRaWAN application data buffer. 
extern uint8_t PayloadEstrutura_buffer[256];
// Lora application data structure. 
extern lmh_app_data_t PayloadEstrutura;

extern uint8_t LoRaAplicPorta;
extern uint32_t g_count;
extern uint32_t g_count_fail;
*/
void Empacota();

TTN LNS meta-data results:

"uplink_message": {
      "session_key_id": "AY7SUS6oCRs/Gv4wTKVC6g==",
      "f_port": 2,
      "f_cnt": 15,
      "frm_payload": "cXEAQABA/DBnZwFHaGiGc3MnxImJ/qEUMP1p8skACW4=",
      "decoded_payload": {
        "accelerometer_113": {
          "x": 0.064,
          "y": 0.064,
          "z": -0.976
        },
        "altitude_137": 24.14,
        "barometer_115": 1018,
        "gps_137": {
          "altitude": 24.14,
          "latitude": -22.997968,
          "longitude": -43.388215
        },
        "humidity_104": 67,
        "location_137": "(-22.997968,-43.388215)",
        "temperature_103": 32.7
      },

Congrats!
And thanks for your contributions here in the forum.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.