Yes of course, I’m going to post the code as soon as I’ve fully tested it
(I will also post the code for working with the Wisblock RGB sensor for a smart home)
The decoder code is large, here are the main functions (they work, but there may be bugs, I haven’t tested everything yet!) Later I will post the Melopero code (my changes)
// Outputting data from an array of structures
void CayenneLPP::printLPP (struct cell *vals, int len)
{
for (int idx = 0; idx < len; idx++)
{
if (vals[idx].channel != 0) {
printf ("ch. [%d], ", vals[idx].channel);
printf ("%s: ", vals[idx].type);
printf ("%.2f\n", vals[idx].data);
}
}
}
// https://stackoverflow.com/questions/50568238/c-char-array-to-uint8-t-array
int CayenneLPP::char2int (char val)
{
return (val >= '0' && val <= '9') ? (val - '0') : (val - 'A' + 10);
}
int CayenneLPP::chars2int (unsigned char const vals[2])
{
return (char2int (vals[0]) << 4) | (char2int (vals[1]));
}
u_int8_t CayenneLPP::decodeData (u_int8_t * buffer, u_int8_t len,
struct cell *data_array)
{
u_int32_t lppunixtime;
u_int8_t count = 0;
u_int8_t index = 0;
while ((index + 2) < len)
{
// Get channel #
u_int8_t channel = buffer[index++];
// Get data type
u_int8_t type = buffer[index++];
if (!isType (type))
{
_error = LPP_ERROR_UNKOWN_TYPE;
return 0;
}
// Type definition
u_int8_t size = getTypeSize (type);
u_int32_t multiplier = getTypeMultiplier (type);
bool is_signed = getTypeSigned (type);
// Check buffer size
if (index + size > len)
{
_error = LPP_ERROR_OVERFLOW;
return 0;
}
// Parse types
if (LPP_COLOUR == type)
{
data_array[count].channel = channel;
data_array[count + 1].channel = channel;
data_array[count + 2].channel = channel;
data_array[count].data =
getValue (&buffer[index], 1, multiplier, is_signed);
data_array[count + 1].data =
getValue (&buffer[index + 1], 1, multiplier, is_signed);
data_array[count + 2].data =
getValue (&buffer[index + 2], 1, multiplier, is_signed);
sprintf (data_array[count].type, "%s r %f", getTypeName (type),
getValue (&buffer[index], 1, multiplier, is_signed));
sprintf (data_array[count + 1].type, "%s g %f", getTypeName (type),
getValue (&buffer[index + 1], 1, multiplier, is_signed));
sprintf (data_array[count + 2].type, "%s b %f", getTypeName (type),
getValue (&buffer[index + 2], 1, multiplier, is_signed));
count = count + 2;
}
else if (LPP_ACCELEROMETER == type || LPP_GYROMETER == type)
{
data_array[count].channel = channel;
data_array[count + 1].channel = channel;
data_array[count + 2].channel = channel;
data_array[count].data =
getValue (&buffer[index], 2, multiplier, is_signed);
data_array[count + 1].data =
getValue (&buffer[index + 2], 2, multiplier, is_signed);
data_array[count + 2].data =
getValue (&buffer[index + 4], 2, multiplier, is_signed);
sprintf (data_array[count].type, "%s x %f", getTypeName (type),
getValue (&buffer[index], 2, multiplier, is_signed));
sprintf (data_array[count + 1].type, "%s y %f", getTypeName (type),
getValue (&buffer[index + 2], 2, multiplier, is_signed));
sprintf (data_array[count + 2].type, "%s z %f", getTypeName (type),
getValue (&buffer[index + 4], 2, multiplier, is_signed));
count = count + 2;
}
else if (LPP_GPS == type)
{
data_array[count].channel = channel;
data_array[count + 1].channel = channel;
data_array[count + 2].channel = channel;
data_array[count].data =
getValue (&buffer[index], 3, 10000, is_signed);
data_array[count + 1].data =
getValue (&buffer[index + 3], 3, 10000, is_signed);
data_array[count + 2].data =
getValue (&buffer[index + 6], 3, 10000, is_signed);
sprintf (data_array[count].type, "%s latitude %f",
getTypeName (type), getValue (&buffer[index], 3, 10000,
is_signed));
sprintf (data_array[count + 1].type, "%s longitude %f",
getTypeName (type), getValue (&buffer[index + 3], 3, 10000,
is_signed));
sprintf (data_array[count + 2].type, "%s altitude %f",
getTypeName (type), getValue (&buffer[index + 6], 3, 10000,
is_signed));
count = count + 2;
}
else if (LPP_GENERIC_SENSOR == type || LPP_UNIXTIME == type)
{
if (LPP_UNIXTIME == type)
{
lppunixtime = getValue32 (&buffer[index], size);
}
else
{
data_array[count].channel = channel;
data_array[count].data = getValue32 (&buffer[index], size);
sprintf (data_array[count].type, "%s", getTypeName (type));
}
}
else
{
data_array[count].channel = channel;
data_array[count].data =
getValue (&buffer[index], size, multiplier, is_signed);
sprintf (data_array[count].type, "%s", getTypeName (type));
}
count++;
index += size;
}
return count;
}
// This function for Wisblock Sensors is to receive LoRa data.
// The function decodes LPP data received via LoRa and prints it
// void lora_data_handler(void), g_rx_lora_data
void decode_lpp ()
{
CayenneLPP lpp (160);
// Decoding received data, example
char tmp_buffer[] = "0802016C076880067325C5026700B404020C96";
// char tmp_buffer[] = "32B59633B59734B59835B59936B59A37B59B38B59C39B59D3CB4000026021FB43DB70000000000FE3EB8000036990D013FB5A340B5A441B5A542B5A643B5A744B5A845B5A9";
assert ((sizeof (tmp_buffer) - 1) % 2 == 0);
u_int8_t buff[(sizeof (tmp_buffer) - 1) / 2];
for (unsigned idx = 0; idx < sizeof (tmp_buffer); idx += 2)
{
buff[idx / 2] = lpp.chars2int ((unsigned char *) tmp_buffer + idx);
}
u_int8_t cnt = lpp.countArray (buff, sizeof (buff));
printf ("cnt = %d\n", cnt);
struct cell *data_array;
data_array = (struct cell *) malloc (cnt * sizeof (struct cell *));
lpp.decodeData (buff, sizeof (buff), data_array);
// Output all sensor data
lpp.printLPP (data_array, cnt);
free (data_array);
}