Arduino Mega Server

Модератор: Alex

arturmon82
Сообщения: 28
Зарегистрирован: Сб июн 06, 2015 6:04 pm
Благодарил (а): 9 раз
Поблагодарили: 3 раза

Re: Arduino Mega Server

Сообщение arturmon82 » Чт авг 13, 2015 9:08 pm

Плюс за json, меньше передаваемых данных проще парсить, давненько даже либу встречал для ардуины.

Отправлено с моего P780 через Tapatalk
Аватара пользователя
uni
Сообщения: 191
Зарегистрирован: Вс июл 26, 2015 9:21 pm
Откуда: Екатеринбург
Благодарил (а): 4 раза
Поблагодарили: 7 раз
Контактная информация:

Re: Arduino Mega Server

Сообщение uni » Пт авг 14, 2015 7:37 am

Вот ссылка на сайт проекта jsmn: http://zserge.com/jsmn.html + исходники: https://bitbucket.org/zserge/jsmn/overview

Похоже, что работа над парсером продолжается и мне стоит обновить свой вариант, т.к. я уже не помню когда его правил.

Вот сравнительная статья с тестами различных парсеров: Comparison and microbenchmark of #JSON parsers

Цитата:
jsmn

http://zserge.bitbucket.org/jsmn.html (MIT)

Парсер для эмбедщины и других сред с ограниченными ресурсами.

Парсинг использует обычный подход с ручной стейт-машиной. Аллокаций памяти ноль, потому что всё предварительно должно быть зааллоцировано в сплошном куске памяти при вызове парсера. Это для моих целей хорошо. Парсер потоковый, то есть его можно рестартовать, если данных не хватило.

Парсер ожидает, что данные в буфере для парсинга будут ASCIIZ, то есть 0-терминированными. Немного неприятно, но тоже себе идиома.
Почему неприятно? Потому что не всегда ноль доступен (например, как парсить JSONP, даже если известны границы JSON?), а поставить '\0' в данный извне буфер идиоматически можно только с его полной реаллокацией.

Тесты делаются как для хороших данных, так и для плохих, неполных. Fuzz-тестов нет.

Претендент выходит в финал.

UPD: Связался с автором jsmn, и он починил работу с выходным массивом. Теперь по производительности парсинга jsmn минимум в пару раз обгоняет все остальные протестированные проекты.
Россия навсегда!
cg_shura
Сообщения: 110
Зарегистрирован: Пт авг 14, 2015 11:24 am
Благодарил (а): 3 раза
Поблагодарили: 6 раз

Re: Arduino Mega Server

Сообщение cg_shura » Пт авг 14, 2015 11:38 am

Парсеры json в embedded упираются не в производительность, а в расход памяти. Особенно актуально для больших json файлов. Не видел парсера который может использовать фиксированный размер буфера для любого размера json, т.е. принимать json по частям, а часть может быть сама по себе невалидна (например скобка открылась, а закрывается она только в следующей части).
Аватара пользователя
uni
Сообщения: 191
Зарегистрирован: Вс июл 26, 2015 9:21 pm
Откуда: Екатеринбург
Благодарил (а): 4 раза
Поблагодарили: 7 раз
Контактная информация:

Re: Arduino Mega Server

Сообщение uni » Пт авг 14, 2015 12:51 pm

cg_shura писал(а):Парсеры json в embedded упираются не в производительность, а в расход памяти. Особенно актуально для больших json файлов. Не видел парсера который может использовать фиксированный размер буфера для любого размера json, т.е. принимать json по частям, а часть может быть сама по себе невалидна (например скобка открылась, а закрывается она только в следующей части).
Это вот он и есть. Можно посмотреть на тесты: Tests.cpp. Имеющихся у него возможностей достаточно для работы на мк.
Нужен только фиксированный буфер, достаточный для одного элемента в понимании jsmn. Если этот один элемент помещается в буфер, то его можно распарсить.
Россия навсегда!
cg_shura
Сообщения: 110
Зарегистрирован: Пт авг 14, 2015 11:24 am
Благодарил (а): 3 раза
Поблагодарили: 6 раз

Re: Arduino Mega Server

Сообщение cg_shura » Пт авг 14, 2015 2:19 pm

uni писал(а):Нужен только фиксированный буфер, достаточный для одного элемента в понимании jsmn. Если этот один элемент помещается в буфер, то его можно распарсить.
Да, но в конце части json парсер выдаст JSMN_ERROR_PART и неопонятно, это часть json обрезанная или действительно ошибка. Надо получать следующую часть json, сращивать недопарсенный кусок с предыдущей и т.д. Как-то муторно и ненадежно, или я недопонял как с ним работать при "скользящем" окне.
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: Arduino Mega Server

Сообщение Alex » Пт авг 14, 2015 2:26 pm

В связи с оптимизацией количество файлов уменьшилось, но увеличился их размер. И теперь стали заметны огрехи передачи файлов на SD карту по Serial (чем больше файл — тем больше вероятность ошибки передачи).

У кого есть возможность разобраться с проблемой передачи файлов по Serial — было бы здорово.
cg_shura
Сообщения: 110
Зарегистрирован: Пт авг 14, 2015 11:24 am
Благодарил (а): 3 раза
Поблагодарили: 6 раз

Re: Arduino Mega Server

Сообщение cg_shura » Пт авг 14, 2015 2:41 pm

Alex писал(а):стали заметны огрехи передачи файлов на SD карту по Serial (чем больше файл — тем больше вероятность ошибки передачи).
А подробнее? В чем заключаются огрехи? Контрольная сумма файла не сходится? Или она не проверяется?
Аватара пользователя
uni
Сообщения: 191
Зарегистрирован: Вс июл 26, 2015 9:21 pm
Откуда: Екатеринбург
Благодарил (а): 4 раза
Поблагодарили: 7 раз
Контактная информация:

Re: Arduino Mega Server

Сообщение uni » Пт авг 14, 2015 2:51 pm

cg_shura писал(а):
uni писал(а):Нужен только фиксированный буфер, достаточный для одного элемента в понимании jsmn. Если этот один элемент помещается в буфер, то его можно распарсить.
Да, но в конце части json парсер выдаст JSMN_ERROR_PART и неопонятно, это часть json обрезанная или действительно ошибка. Надо получать следующую часть json, сращивать недопарсенный кусок с предыдущей и т.д. Как-то муторно и ненадежно, или я недопонял как с ним работать при "скользящем" окне.
Но ведь похож на потоковый парсер? Если мегабайты в мк не посылать, то можно и поработать? Я уже точно не помню, но по идее resume должен быть реализован, нужно лишь подвинуть указатель на начало буфера и сбросить ошибку.

Я давно его переделывал и не помню есть это или нет.
Россия навсегда!
Alex
Сообщения: 2357
Зарегистрирован: Пт апр 20, 2012 12:53 pm
Благодарил (а): 42 раза
Поблагодарили: 262 раза

Re: Arduino Mega Server

Сообщение Alex » Пт авг 14, 2015 4:35 pm

А подробнее? В чем заключаются огрехи? Контрольная сумма файла не сходится? Или она не проверяется?
Файлы передаются потоковым методом. Processing закачивает файл в бинарном формате в массив и в цикле посылает в сериал. Но есть проблема: просто передать файл мало, нужно ещё в потоке умудриться передать имя файла (работа с директориями пока не поддерживается). Для того, чтобы передать мета-информацию (имя файла) в поток подмешиваются маркеры, которые в потоке выделяются на стороне Ардуины и при их помощи получается имя файла.

На стороне Ардуины потоковый декодер отделяет мета-информацию и записывает поток в файл. Название файла — из выделенных маркеров.

Всё это работает нормально процентов на 95 на небольших файлах и чем больше файл — тем больше вероятность ошибки. Проявляется в появлении мусора, потери части информации или преждевременном завершении передачи.

Я проверял код с обоих сторон и не нашёл ничего, что так может влиять на передачу. Причина дефекта мне не известна.

Замечено, что часто ошибка происходит в начале файла и введён «костыль» (функция errorProtection), который после первой строки принудительно шлёт массив мусора (на этот массив и приходится ошибка) и на стороне Ардуины этот массив отбраковывается и не пишется в файл.

Таким образом нужно установить причину возникновения ошибок передачи и добиться точной байт в байт передачи файлов. Сейчас более-менее нормально передаются только текстовые файлы. Картинку пока передать не получится.
cg_shura
Сообщения: 110
Зарегистрирован: Пт авг 14, 2015 11:24 am
Благодарил (а): 3 раза
Поблагодарили: 6 раз

Re: Arduino Mega Server

Сообщение cg_shura » Пт авг 14, 2015 6:42 pm

Alex писал(а):Но есть проблема: просто передать файл мало, нужно ещё в потоке умудриться передать имя файла
Просмотрел arduino_mega_server\upload.ino, это же оно? Не удивительно, что могут быть ошибки. Сложно понять что где. Для начала я бы сделал конечный автомат, типа такого:

enum UploadFileState
{
UFS_IDLE,
UFS_WAIT_FILE_DESC,
UFS_WAIT_FILE_PART,
US_FILE_ARRIVED
}

struct FileDesc
{
char fileName[20];
int fileSize;
int fileCrc32;
}

...

FileDesc _fileDesc;
UploadFileState _state = UFS_WAIT_FILE_DESC;
int _writenFileSize = 0;
File _file;

...

void loop()
{

switch (_state)
{
case UFS_WAIT_FILE_DESC:
{
// Если что-то есть в Serial - значит это заголовок файла. А именно: имя файла, его размер и CRC32.
if (serial.available())
{
serial.readBuffer(&_fileDesc, sizeof(_fileDesc));
_file.create(_fileDesc.fileName);
_state = UFS_WAIT_FILE_PART;
}
break;
}

case UFS_WAIT_FILE_PART:
{
// Если что-то есть в Serial - значит это кусок файла. А именно: имя файла, его размер и CRC32.
if (serial.available())
{
static char buff[128];
int readLen = serial.readBuffer(&buff, sizeof(buff));

_file.writeBuffer(&buff, readLen);
_writtenFileSize += readLen;

if (_writtenFileSize >= _fileDesc.fileSize)
_state = UFS_FILE_ARRIVED;
}
break;
}

case UFS_WAIT_FILE_PART:
{
// Проверяем что СRC32 принятого файла равно _fileDesc.CRC32 и если это не так - удаляем файл
break;
}
...
}
}
Ответить