Простой универсальный протокол для передачи данных через Arduino Stream (Serial, Wire, итд)
- Контроль целостности
- 256 типов пакетов
- Асинхронный приём
- Возможность chunked отправки
Совместима со всеми Arduino платформами (используются Arduino-функции)
Библиотека предназначена для эффективной отправки и чтения пакетов по Arduino Stream. При отправке пакету присваивается тип пакета - число 8 бит. При парсинге это число будет доступно для того, чтобы кастовать данные в нужный ожидаемый тип. Например отправим 32 бит число, тип пакета 1 и кусок строки, тип пакета 2:
uint32_t val = 12345;
StreamPacket::send(Serial, 1, val); // тип пакета 1 (автоопределение длины)
char str[] = "hello";
StreamPacket::send(Serial, 2, str, 5); // тип пакета 2, длина 5 (без нулевого символа)
Библиотека составит и отправит пакет, он имеет следующую структуру:
- Заголовок
- Стартовый байт
- Длина (2 байта)
- Тип (1 байт)
- CRC (1 байт)
- Данные
- Данные
- CRC (1 байт)
При парсинге библиотека проверит корректность данных и отправит их в обработчик. В нём можно разобрать данные, исходя из типа пакета, и кастовать их в нужный тип. Библиотека также отправляет длину пакета, что позволяет принимать динамические данные:
void loop() {
StreamPacket::parse(Serial, [](uint8_t type, void* data, size_t len){
switch (type) {
case 1:
// тип 1 - 32 бит целое
Serial.println("type 1");
Serial.println(*((uint32_t*)data));
break;
case 2:
// тип 2 - строка (длины len)
Serial.println("type 2");
Serial.write((char*)data, len);
Serial.println();
break;
}
});
}
Удобнее всего использовать для передачи структуры - см. примеры ниже.
Синхронная отправка и приём
// отправить данные
bool StreamPacket::send(Stream& s, Tp type, const Td& data);
// отправить данные
bool StreamPacket::send(Stream& s, Tp type, const void* data, size_t len);
// парсить данные, коллбэк вида f(uint8_t type, void* data, size_t len)
void StreamPacket::parse(Stream& s, ParseCallback cb);
Chunked отправщик
Sender(Stream& s);
// начать пакет
bool beginPacket(Tp type, size_t len);
// отправить чанк
bool send(const Td& data);
// отправить чанк
bool send(const void* data, size_t len);
// завершить отправку
bool endPacket();
Асинхронный парсер, работает на буфере Stream (пакеты до 64 байт AVR, 128 байт ESP)
// коллбэк вида f(uint8_t type, void* data, size_t len)
Reader(Stream& s, ParseCallback cb = nullptr);
// коллбэк вида f(uint8_t type, void* data, size_t len)
void onData(ParseCallback cb);
// тикер, вызывать в loop
void tick();
Асинхронный парсер со своим буфером на любой размер
// коллбэк вида f(uint8_t type, void* data, size_t len)
ReaderBuf(Stream& s, ParseCallback cb = nullptr);
// коллбэк вида f(uint8_t type, void* data, size_t len)
void onData(ParseCallback cb);
// тикер, вызывать в loop
void tick();
struct S {
int a;
float b;
char str[5];
};
S s{123, 3.14, "abcd"};
StreamPacket::send(Serial, 1, s); // тип пакета 1
char str[] = "hello";
StreamPacket::send(Serial, 2, str, 5); // тип пакета 2, длина 5
StreamPacket::Sender s(Serial);
s.beginPacket(3, 17); // тип пакета 3, длина 17 байт
s.send("hello ", 6);
s.send("world ", 6);
s.send("12345", 5);
s.endPacket();
void loop() {
StreamPacket::parse(Serial, [](uint8_t type, void* data, size_t len){
switch (type) {
case 1:
Serial.println("type 1");
Serial.write((char*)data, len);
break;
case 2:
Serial.println("type 2");
Serial.write((char*)data, len);
break;
case 3: {
Serial.println("type 3");
S& s = *((S*)data);
Serial.println(s.a);
Serial.println(s.b);
Serial.println(s.str);
} break;
}
Serial.println();
});
}
StreamPacket::Reader p(Serial, [](uint8_t type, void* data, size_t len){
switch (type) {
case 1:
Serial.println("type 1");
Serial.write((char*)data, len);
break;
case 2:
Serial.println("type 2");
Serial.write((char*)data, len);
break;
case 3: {
Serial.println("type 3");
S& s = *((S*)data);
Serial.println(s.a);
Serial.println(s.b);
Serial.println(s.str);
} break;
}
Serial.println();
});
void loop() {
p.tick();
}
- v1.0
- Библиотеку можно найти по названию StreamPacket и установить через менеджер библиотек в:
- Arduino IDE
- Arduino IDE v2
- PlatformIO
- Скачать библиотеку .zip архивом для ручной установки:
- Распаковать и положить в C:\Program Files (x86)\Arduino\libraries (Windows x64)
- Распаковать и положить в C:\Program Files\Arduino\libraries (Windows x32)
- Распаковать и положить в Документы/Arduino/libraries/
- (Arduino IDE) автоматическая установка из .zip: Скетч/Подключить библиотеку/Добавить .ZIP библиотеку… и указать скачанный архив
- Читай более подробную инструкцию по установке библиотек здесь
- Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
- Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
- Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
При нахождении багов создавайте Issue, а лучше сразу пишите на почту [email protected]
Библиотека открыта для доработки и ваших Pull Request'ов!
При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
- Версия библиотеки
- Какой используется МК
- Версия SDK (для ESP)
- Версия Arduino IDE
- Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
- Какой код загружался, какая работа от него ожидалась и как он работает в реальности
- В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код