Arduino KVComm  master
Key-Value pair communication library for Arduino
KVComm-Receive.ino

KVComm-Receive

Receives SLIP packages containing a KV dictionary and print the keys and values.

Boards:
AVR, AVR USB, Nano Every, Nano 33, Due, Teensy 3.x, ESP8266, ESP32
See also
KVComm-Send.ino

Written by PieterP, 2020-02-08
https://github.com/tttapa/Arduino-KVComm

#include <KVComm.h>
#include <boost/crc.hpp>
// The CRC settings to use, must be the same as the sender.
using CRC = boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false>;
// Buffer for saving the incoming packets
uint8_t slipbuffer[256];
// The actual SLIP Stream: it sends and receives packets, adds framing
// bytes, and computes a checksum using the CRC specified above.
Serial, // stream
CRC(), // sender CRC
slipbuffer, // parser
CRC(), // parser CRC
};
void setup() {
Serial.begin(115200);
CRC()(0); // initialize the CRC lookup table (see footnote below)
}
// Function that is called when a new packet is received
void handlePacket(const uint8_t *data, size_t length);
void loop() {
// Try to read a packet
size_t packetSize = slip.readPacket();
// If a packet was received
if (packetSize > 0) {
// Check the integrity of the packet, and make sure it wasn't truncated
if (slip.checksum() == 0 && !slip.wasTruncated())
handlePacket(slipbuffer, packetSize);
else
Serial.println("<< Invalid packet >>"), Serial.println();
}
}
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
// Print a key-value dictionary entry
template <class T>
void printEntry(const KV_Iterator::KV &entry) {
Serial.print(entry.getID()), Serial.println(':');
Serial.print(" ");
uint16_t numElem = entry.getArraySize<T>();
for (uint16_t i = 0; i < numElem; ++i)
Serial.print(entry.getAs<T>(i)), Serial.print(i + 1 < numElem ? ", " : "");
Serial.println(), Serial.println();
}
// Print a key-value dictionary entry: specialization for strings.
template <>
void printEntry<char>(const KV_Iterator::KV &entry) {
Serial.print(entry.getID()), Serial.println(':');
Serial.print(" ");
Serial.println(entry.getString());
Serial.println();
}
void handlePacket(const uint8_t *data, size_t length) {
// Iterate over all key-value pairs in the dictionary
for (auto &entry : KV_Iterator(data, length)) {
// Determine the type of the value, and print it
switch (entry.getTypeID()) {
case KV_Type<int>::getTypeID(): printEntry<int>(entry); break;
case KV_Type<float>::getTypeID(): printEntry<float>(entry); break;
case KV_Type<char>::getTypeID(): printEntry<char>(entry); break;
}
}
Serial.println("====================");
Serial.println();
}
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
// On initializing the CRC
// -----------------------
//
// The Boost::CRC library uses a lookup table to speed up the CRC calculations.
// This table is created the first time the CRC is used, and this process takes
// a significant amount of time.
// This is a problem when receiving large packets: when the first byte of the
// packet arrives, the CRC is used for the first time, and it starts generating
// the lookup table. But in the meantime, more bytes from the packet keep coming
// in. These bytes cannot be read while the lookup table is being created, so
// they quickly fill up the input buffer, until it overflows. When this happens,
// bytes are dropped, and data is lost.
//
// The solution is simple: use the CRC once in the setup, so the lookup table
// is created before the program starts receiving data.
KV_Iterator
Class for iterating over a dictionary generated by the KV_Builder, used for parsing and for checking ...
Definition: KV_Iterator.hpp:42
KV_Iterator::KV
Definition: KV_Iterator.hpp:47
KVComm.h
KV_Type::getTypeID
constexpr static uint8_t getTypeID()
KV_Iterator::KV::getTypeID
uint8_t getTypeID() const
Get the type ID of the current element.
Definition: KV_Iterator.hpp:52
KV_Iterator::KV::getString
std::string getString() const
Get the character array as an std::string.
Definition: KV_Iterator.cpp:57
SLIPStreamCRC::readPacket
size_t readPacket()
Receives a packet into the read buffer.
Definition: SLIPStream.ipp:30
KV_Iterator::KV::getAs
T getAs(size_t index=0) const
Get the data as the given type.
Definition: KV_Iterator.hpp:132
SLIPStreamCRC::checksum
checksum_t checksum() const
Get the checksum of the previous packet.
Definition: SLIPStream.hpp:125
KV_Iterator::KV::getArraySize
uint16_t getArraySize() const
Get the number of elements in the array of data.
Definition: KV_Iterator.hpp:72
SLIPStreamCRC::wasTruncated
bool wasTruncated() const
Check if the previous packet was truncated.
Definition: SLIPStream.hpp:117
SLIPStreamCRC
Class that implements SLIP, a simple packet framing protocol, and that uses cyclic redundancy checks ...
Definition: SLIPStream.hpp:84
KV_Iterator::KV::getID
const char * getID() const
Get the identifier / key of the current element.
Definition: KV_Iterator.hpp:62
SLIPStream.hpp