Стартовая страница › Форумы › Разработка и интеграция › 48 попугаев при опросе
- В этой теме 27 ответов, 3 участника, последнее обновление 2 года назад сделано Mikhail.
-
АвторСообщения
-
11.03.2022 в 21:16 #22296manjey73Участник
Ситуация такая, опрашиваю устройство, у которого длина ответа вариативная (вечно мне такие попадаются)…
Так вот, ответы в общем короткие и сделал опрос по одному байту после заголовка с проверкой на маркер в виде байта 0xC0
Количество маркеров зависит от наличия определенных байт в блоке данных.Вот код
private void ReadAfterHeader(int needCnt, out int Cnt, out string log) { int startRead = 5; Cnt = 0; int cnt = 0; int cnt1 = 0; for (int i = 0; i < needCnt; i++) { cnt1 = Connection.Read(inBuf, startRead, 1, ReqParams.Timeout, CommUtils.ProtocolLogFormats.Hex, out logText); if (inBuf[startRead] == 0xC0) { i--; } cnt += cnt1; startRead++; } Cnt = cnt; log = Connection.BuildReadLogText(inBuf, 5, Cnt, CommUtils.ProtocolLogFormats.Hex); }
Есть возможность целенаправленно задать эти определенные байты в ответе (это счетчик, начальное значение которого можно задать)
Так вот через 48-мь сессий опроса прибора происходит ошибка чтения, независимо сколько запросов я делаю, 5-ть или 3-ри…В чем может быть проблема? Если что могу дать драйвер и доступ к прибору…
Ошибка
Отправка (9): C1 06 01 00 02 8A 03 60 48 Приём (5/5): C2 06 01 00 05 2022-03-11 12:40:01 Ошибка при выполнении сеанса опроса КП 153 "RIELTA": Ошибка при считывании данных: Заданный аргумент находится вне диапазона допустимых значений. Имя параметра: size
12.03.2022 в 08:25 #22299manjey73УчастникНашел причину, но не понимаю, как это работает. Количество Сессий зависит от размера буфера.
Были объявлены переменные
private const int InBufLen = 20; // Длина буфера принимаемых данных private byte[] inBuf; // буфер входных данных
В разделе OnAddedToCommLine() было объявление
inBuf = new byte[InBufLen];
Connection.Read вроде как бы намекает, что чтение происходит в определенный offset но где-то происходит переполнение буфера…
Перенес объявление буфера непосредственно в Session и ошибка ушла…
Что самое интересное, ловил маркер циклами while и for чтением по одному байту, переделал на вариант от : Connection.BinStopCondition, ошибка все равно происходила. Количество сессий (попугаев), после которых происходила ошибка зависит от размера буфера InBufLen первоначально был 60 байт, отсюда и 48 попугаев 🙂Но вот с чем связана такая ошибка непонятно????
12.03.2022 в 10:29 #22302MikhailМодераторConnection.Read вроде как бы намекает, что чтение происходит в определенный offset
Верно. Новые данные записываются в указанные ячейки буфера.
Перенес объявление буфера непосредственно в Session и ошибка ушла
Так будет постоянно выделяться новая память, что нежелательно.
Думаю, что ошибку нужно отловить и вывести в журнал дополнительную информацию, которая поможет найти причину.
12.03.2022 в 10:31 #22303MikhailМодераторПеременная i цикла for не должна меняться в теле цикла. Сделайте хотя бы цикл while вместо for.
12.03.2022 в 11:04 #22304manjey73УчастникМихаил, я думаю ошибка в ядре Коммуникатора при задании буфера в секции OnAddedToCommLine()
цикл for это второй вариант при поиске проблемы, сейчас работает по схеме остановки массива байт в созданном классе от Connection.BinStopCondition
То есть ошибка проявлялась при любых из трех вариантов и определенном ответе.
з.ы. сейчас отключу запрос для данного ответа и верну буфер где был и проверю.
Если что могу дать и код драйвера и доступ к железке для поиска…
Почему это i нельзя менять в for? кто это запретил ? 🙂
- Этот ответ был изменен 2 года назад от manjey73.
12.03.2022 в 11:26 #22306manjey73УчастникСейчас код такой.
private readonly static MyStopCondition StopCond; private static List<byte[]> stopList = new List<byte[]>(); private static byte[] cx0 = new byte[] { 0xC0 }; // 0xC0, 0x00 public class MyStopCondition : Connection.BinStopCondition // TEST логики остановки по двум или более массивам { public MyStopCondition(List<byte[]> stopL) { Stop = stopL; } public List<byte[]> Stop { get; private set; } public override bool CheckCondition(byte[] buffer, int index) { foreach (var stop in Stop) { StopSeq = stop; if (base.CheckCondition(buffer, index)) return true; } return false; } } private void ReadAfterHeader(int needCnt, byte[] buffer, byte lastByte, out int readCnt, out string logText) { bool stopReceived = false; bool checkWhile; readCnt = 0; int offset = 5; do { checkWhile = true; int readCnt1 = Connection.Read(buffer, offset, needCnt, ReqParams.Timeout, StopCond, out stopReceived, CommUtils.ProtocolLogFormats.Hex, out logText); if (stopReceived) { offset = offset + readCnt1; needCnt = offset - 1; } else checkWhile = false; readCnt += readCnt1; } while (checkWhile); logText = Connection.BuildReadLogText(buffer, 5, readCnt, CommUtils.ProtocolLogFormats.Hex); }
Далее в разделе задан список
static KpRieltaLogic() { stopList.AddRange(new[] { cx0 }); // , cx1, cx2 StopCond = new MyStopCondition(stopList); }
При включении запроса, в ответе которого будет маркер 0xC0 при размере буфера 20 байт, заданным в OnAddedToCommLine() через 8 сессий получаем ошибку
Отправка (9): C1 06 01 00 02 8A 03 60 48 Приём (5/5): C2 06 01 00 05 2022-03-12 11:19:00 Ошибка при выполнении сеанса опроса КП 153 "RIELTA": Ошибка при считывании данных с условием остановки: Заданный аргумент находится вне диапазона допустимых значений. Имя параметра: size
При этом MyStopCondition можно убрать и сделать либо простым циклом, либо циклом while, меняя там количество байт для Connection.Read приводят все равно к ошибке…
Если буфер задан в Session то все работает (всю ночь на остановке по массиву байт отработало без нареканий.)Каким образом нарушается буфер, при включении его в OnAddedToCommLine() при том, что в Connection.Read явно указывается с какого байта заполнять буфер ????
12.03.2022 в 12:33 #22311manjey73УчастникВключение буфера в OnCommLineStart() приводит к тому же результату с ошибкой.
Такая вот картина…
Коммуникатор
Версия : 5.2.1.212.03.2022 в 12:34 #22312RomirosУчастникНаверное тут лучше запустить debugger и не гадать. Всё пошагово будет видно.
12.03.2022 в 12:41 #22313RomirosУчастникИ можно ещё проверить, если очищать буфер перед опросом, ошибка будет повторяться?
12.03.2022 в 15:02 #22315manjey73УчастникА как очищать? Циклом нули писать?
Фокус в том, что ответ без маркера 0xC0 читается через тот же код, будь это цикл или по остановке через массив байт, не приводит к ошибке.
Попробую через дебаггер подключить и понять где остановится, но честно не знаю куда остановку ставить, так как проблема не в моём коде точно.12.03.2022 в 15:28 #22316RomirosУчастникОчистить как-то так
Array.Clear(inBuf,0,inBuf.Length)Ошибка у Вас в коде. Дебагер поможет. Сам через это проходил. У меня проблема была конечно в другом, то что в неуправляемом коде размер типов в байтах другой, чем в управляемом. И у меня так же индекс выходил за диапазон. Я просто не знал этого ньюанса и по логике кода все должно было работать. Потом подключил дебагер и просто офигел, насколько отличается размер.
12.03.2022 в 20:32 #22322manjey73УчастникОшибка буфера ситуацию не изменила, осталось все по прежнему.
К сожалению, у меня нет под рукой Allen Bradley чтобы проверить, там был похожий механизм, но маркер в коде был 0x10, не помню на какой версии, работало сутки на пролет без проблем.
- Этот ответ был изменен 2 года назад от manjey73.
12.03.2022 в 20:38 #22324manjey73УчастникВопрос, а к какому процессу надо подключиться и как? ScadaComm запущен же как сервис и я не вижу его…
12.03.2022 в 20:49 #22325manjey73УчастникSystem.InvalidOperationException: "Ошибка при считывании данных с условием остановки: Заданный аргумент находится вне диапазона допустимых значений. Имя параметра: size"
ArgumentOutOfRangeException: Заданный аргумент находится вне диапазона допустимых значений. Имя параметра: size
Исключение в Connection.Read
Почему-то буфер стал всего 12 byte[12]12.03.2022 в 20:56 #22326manjey73УчастникУ меня простой вопрос, почему буфер, объявленный в OnAddedToCommLine() при передаче в Connection.Read в режиме с остановкой начинает уменьшаться на один байт каждую сессию ?
Это мое предположение, я то его никак не уменьшаю в коде…
-
АвторСообщения
- Вы должны авторизироваться для ответа в этой теме.