Ошибка DrvCnlBasic

Просмотр 15 сообщений - с 1 по 15 (из 65 всего)
  • Автор
    Сообщения
  • #38898
    manjey73
    Участник
    
    Приём (7/7): FF 10 00 90 01 00 8C
    2025-06-13 23:44:30 Ошибка при вызове метода Session устройства [9999] Logika:
    Scada.ScadaException: Ошибка при считывании данных: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. (Parameter 'count')
     ---> System.ArgumentOutOfRangeException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. (Parameter 'count')
       at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 count)
       at Scada.Comm.Drivers.DrvCnlBasic.Logic.TcpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
       --- End of inner exception stack trace ---
       at Scada.Comm.Drivers.DrvCnlBasic.Logic.TcpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
       at Scada.Comm.Channels.Connection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout)
    

    Тут привел главное. Суть ошибки, прибор висит за модемом, при ответе от которого в начале пакета прилетает один FF, такое уже было, не помню, в драйвере Логика кажется и было. Были случаи что прилетали два FF в начале. После чего происходят чудеса..
    Чудо заключается в том, что DrvCnlBasic начинает возвращать кучки пришедшего первый раз буфера каждые следующие 30 секунд (время периода опроса Сессии).
    Не с начала, а именно кусками.

    правильный ответ
    ‘Приём (7/7): 10 00 90 01 00 8C 00
    Приём (142/142): 72 47 04 00 11 2A 03 48 04 0E 06 19 05 43 04 54 9F 82 41 43 04 EE 22 8E 3F 43 04 3D 29 8D 3F 43 04 00 00 00 00 43 04 D2 AC 8A 3F 43 04 5F F9 8A 3F 43 04 00 00 00 00 16 21 4C 6F 67 69 6B 61 20 43 6F 72 70 20 53 50 54 39 34 31 2D 32 30 20 76 31 2E 30 2E 30 2E 30 2E 30 34 05 00 05 00 05 00 05 00 44 08 92 03 00 00 62 70 45 3F 44 08 00 00 00 00 00 00 00 00 41 04 03 00 00 00 43 04 A9 94 94 42 43 04 05 DA 67 42 05 00 05 00 4A FE
    OK
    `

    А теперь с примера выше только куски показываю
    Приём (7/7): FF 10 00 90 01 00 8C
    Приём (7/7): 00 72 47 04 00 2F 2A
    Приём (7/7): 03 48 04 0E 06 19 05
    и так далее каждые 30 секунд, при этом выпадая в исключение. То есть простое искажение данных может привести к подобному эффекту.

    файл линии

    Приём (7/7): 10 00 90 01 00 8C 00 — здесь 8С 00 это размер пакета, который необходимо прочитать — 140 байт, при искажении пакета получаем 00 8С = 35840 байт (первый байт младший) и понеслось 🙂

    #38899
    manjey73
    Участник

    Мне кажется проблема даже не в ответе от модема, а именно в DrvCnlBasic и эта ошибка древняя как мамонт, еще с 5-й версии. Он однажды решает прилепить 1 или 2 FF и вернуть вместе с реальным ответом.

    как это отловить даже не представляю.

    #38900
    manjey73
    Участник

    Да, еще была другая ситуация, кажется на драйвере Меркурия.
    В настройках стояло 3 повтора при неудачном чтении.
    1-й запрос (а) — нет ответа
    2-й запрос (б) — нет ответа
    3-й запрос (в) — нет ответа
    переход к следующему запросу других параметров
    1-й запрос — в ответе 1-й ответ (а) на предыдущие запросы и как следствие ошибка
    2-й запрос — в ответе 2-й ответ (б) на предыдущий запрос
    3-й запрос — в ответе 3-й ответ (в) на предыдущий запрос

    Вот если я посылаю в прибор НОВОЕ, то кто мне возвращает предыдущие буферы ответов с такой задержкой ?

    #38901
    manjey73
    Участник

    while (RequestNeeded(ref tryNum))

    В общем одна проблемка сидит в скорости связи и повторными запросами.

    Например связь ок, мы выставили timeout 1500 мс и все прекрасно работает.
    Так как там модем, его периодически плющит по скорости и он начинает передавать медленнее и не укладывается в отведенные 1500мс даже с запасом вроде бы.

    Мы честно, отправляем следующий запрос по счетчику попыток, а в ответ получаем хвост предыдущего запроса.

    А вот вторая проблема непонятно с чем связана? следующая сессия у нас через 30 секунд, а мы получаем следующую партию из буфера, при чем не с начала, а вот кусками передвигаясь по буферу, который формируется в DrvCnlBasic. Вот этого поведения я не понимаю… 30 секунд прошло от ошибки опроса, весь ответ успевает прилететь по скорости за 600-700 мс, ну пусть timeout отработал и даже ответ весь не пришел. Но откуда он берет куски на следующем периоде опроса через 30 секунд?

    #38935
    Mikhail
    Модератор

    Какой тип канала связи используется?

    #38936
    manjey73
    Участник

    TCP-Client используется.
    появление первых FF стал контролировать, так же, если пришел мусор вдруг, контролирую и размер следующего пакета, чтобы он был менее 300 байт (такой буфер задан для входящего).
    То есть если прочтет первые 7 байт и в начале нет FF, и вдруг это мусор, то там разер может быть в никуда.

    Ошибок стало поменьше гораздо.

    Кто эти ff присылает непонятно от слова совсем. А вот откуда на следующей сессии через 30 секунд продолжение пакета, которых уже быть не должно точно в толк не возьму.

    За счет контроля размера пакетов избавился от выпадания в осадок (исключения) DrvCnlBasic

    • Ответ изменён 1 год назад пользователем manjey73.
    • Ответ изменён 1 год назад пользователем manjey73.
    #38969
    Mikhail
    Модератор

    Проверьте в драйвере, что в случае неверных данных статус устройства устанавливается в ошибку.
    Здесь в случае ошибки из буфера вычитываются оставшиеся данные.

    #38971
    manjey73
    Участник

    Вручную можно в драйвере статус перевести в ошибку ?
    Или наоборот, чтобы не было чтения из буфера.

    #39017
    Mikhail
    Модератор

    Статус устройства устанавливается логикой драйвера. Посмотрите пример в существующих драйверах.

    #39089
    manjey73
    Участник

    Добавил DeviceStatus = DeviceStatus.Error; внутрь while (TryNum в случае ошибки, но особо ничего не поменялось. После первого запроса идет второй и в ответ левые данные.

    Но последующие запросы вроде идут с нуля и все ок.

    В какой момент отрабатывает DeviceStatus.Error ? уже в конце сессии?
    Как очистить буфер внутри while(TryNum в общем? есть такая возможность?

    #39090
    manjey73
    Участник

    не помогает, посыпались ошибки массово и буфер не очищается. Или это совсем не то, что требовалось сделать ?

    #39101
    Mikhail
    Модератор

    Канал связи очищает буфер уже после сессии. То есть, если проверка показала, что начало пакета содержит некорректные данные, то нужно установить статус в ошибку и больше ничего не считывать в этой сессии.

    #39103
    manjey73
    Участник

    хм, принцип понял.
    Возможная причина, о которой подзабыл, вероятно в опрос вмешивается РСО 🙂
    я к действующему прибору подключаюсь.

    #39167
    manjey73
    Участник

    хм, все равно буфер не очищается.
    Для теста взял другой драйвер, и выставил низкий Timeout, на следующей сессии идет мусор вместо начальных значений ответа.

    #39168
    manjey73
    Участник
    2025-06-24 00:22:50 Соединение с 192.168.0.8:4001
    
    2025-06-24 00:22:50 Сеанс связи с устройством [49] Mbus_SDM
    Отправка (5): 10 40 FD 3D 16
    Отправка (9): 68 03 03 68 53 01 B1 05 16
    Приём (4/4): 68 90 90 68
    Приём (70/146): 08 01 72 78 56 34 12 FF FF 01 02 55 00 00 00 0B FD 47 65 29 02 0B FD 47 00 00 00 0B FD 47 00 00 00 0B FD 47 00 00 00 0B FD 47 00 00 00 0B FD 47 00 00 00 0B FD 59 19 04 00 0B FD 59 00 00 00 0B FD 59 00 00 00 0B
    Ошибка: некорректная длина ответа!
    Получено за 788 мс
    
    2025-06-24 00:23:00 Сеанс связи с устройством [49] Mbus_SDM
    Отправка (5): 10 40 FD 3D 16
    Отправка (9): 68 03 03 68 73 01 B1 25 16
    Приём (4/4): 2A 45 09 00
    Приём (71/71): 0B 2A 00 00 00 0B 2A 00 00 00 0B FD 3A 88 01 00 0B FD 3A 88 01 00 0B FD 3A 00 00 00 0B FD 3A 00 00 00 0A FD 3A 80 09 0A FD 3A 80 09 0A FD 3A 00 00 0A FD 3A 00 00 0A FD 3A 99 49 B3 16 68 90 90 68 08 01 72 78 56 34
    Ошибка: некорректная длина ответа!
    Получено за 484 мс
    

    вот пример.
    При некорректной длине ответа выставляется fatalerror в true и перед FinishSession

    if (fatalerror) DeviceStatus = DeviceStatus.Error; // Test
    FinishSession();

    А ведь при очистке данных буфера входные данные должны же быть с начала ?

Просмотр 15 сообщений - с 1 по 15 (из 65 всего)
  • Для ответа в этой теме необходимо авторизоваться.