УкраїнськаEnglishmRussian
Вход/Новый
В теме нет новых постов

[BugFixed] LTS 0.9.x Некорректная работа Serial с собственным протоколом


Автор Сообщение
Сообщение создано: 16. 05. 2022 [13:45]
Syberian
Oleg Dontsov
Создатель темы
Зарегистрирован(а) с: 11.04.2016
Сообщения: 3
Добрый день.

Проблема: При работе с транспортом Serial собственного протокола пользователя из ответа приходит только первый байт, остальное висит в буфере и может быть вычитано через cat /dev/ttyUSB0

Анализ:
Причина в файле mod_serial.cpp, функция TTrOut::MessIO, в функции приема:

JAVASCRIPT
// * Force wait any data in the request mode or EAGAIN
	    // * No wait any data in the not request mode but it can get the data later
	    for(int iRtr = 0; (((blen=read(fd,iBuf,iLen)) == 0 && !notReq) || (blen < 0 && errno == EAGAIN)) && iRtr < time; ++iRtr)
		TSYS::sysSleep(1e-3);


При опросе готового модуля ModBus в функцию MessIO передается последним 5-м параметром таймаут ответа, который помещается в time. В пользовательском протоколе на входе 4 параметра, time по дефолту =0. Поэтому данная процедура выполняется всегда только 1 раз, после чего MessIO завершается, приняв только 1 байт ответа.

Решение:
Переписал этот участок кода так, чтобы при нулевом time таймаут брался из символьного таймаута в параметрах Serial, а чтение повторялось до тех пор, пока принимаются байты и нет символьного таймаута, либо пока не заполнен входной буфер.

JAVASCRIPT
//===============================================	
		/*
		Процедура чтения до символьного либо общего (если указан) таймаута
		Вход: 
		notReq - ответ НЕ требуется
		blen - число принятых байт / еррор если < 0
		time - таймаут с последнего символа входной
		wCharTm - таймаут символа (мс)
 
		Было раньше: чтение до таймаута time, blen не накапливается
		Изменение: blen накапливает принятые байты, процедура чтения повторяется,
		           пока с последнего символа не вылезет таймаут WCharTm
				   READ выполняется в промежуточный буфер
		*/
		blen=0;
		int iRtr=0;
		int bidx=0; // index counter
		ssize_t blen1=0;
		int itmo;
		itmo=time ? time :  wCharTm;
 
		while(1) {
		 TSYS::sysSleep(1e-3);
		 blen+=vmax(0,blen1);
		 blen1=read(fd, &iBuf[bidx],iLen-bidx);
		if (blen1 < 0 && errno != EAGAIN) {blen=blen1; break;}	// exit on error
		if (blen1 == 0 && notReq) {blen=blen1;break;}			//no response required
		if (blen1 > 0) {iRtr=0; bidx+=blen1;}                   // clear  last symbol timeout, move buffer index
		if (iRtr++ >=itmo) {blen+=vmax(0,blen1); break;} // timeout exit
				}
 
 
	//===============================================
Сообщение создано: 16. 05. 2022 [13:59]
roman
Roman Savochenko
Moderator
Contributor
Developer
Зарегистрирован(а) с: 12.12.2007
Сообщения: 3742
Что не ошибка, тем более для LTS, поскольку этот протокол не предназначен для работы через Serial, а соответственно не имеет механизмов контроля целостности и ожидает как минимум прихода заголовка целиком, чего Serial не гарантирует!

Learn, learn and learn better than work, work and work.
Сообщение создано: 02. 05. 2023 [20:26]
roman
Roman Savochenko
Moderator
Contributor
Developer
Зарегистрирован(а) с: 12.12.2007
Сообщения: 3742
"roman" wrote:

Что не ошибка, тем более для LTS, поскольку этот протокол не предназначен для работы через Serial, а соответственно не имеет механизмов контроля целостности и ожидает как минимум прихода заголовка целиком, чего Serial не гарантирует!


Сейчас Собственный Протокол отдельно ожидает заголовок, а потом весь ответ и корректно обрабатывает попытки и ошибки.
Ну и фрагментация чуть ли не по байтам для него не проблема, т.е. работает с Serial, что однако не снимает проблемы проверки целосности если этот Serial — реальная физическая шина с потенциальным искажением трафика.

Исправлено!

Learn, learn and learn better than work, work and work.



2296