Время ожидания или Timeout

Просмотр 15 сообщений - с 31 по 45 (из 70 всего)
  • Автор
    Сообщения
  • #27172
    manjey73
    Участник

    а когда останавливаться ? 🙂 пример приводил выше, данные от 200 до 250 байт, обрыв связи когда принято всего 100 ?

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

    #27173
    JurasskPark
    Участник

    Я могу сказать одно… не доставку пакета всё равно ничего не спасет.
    А так чтобы NetworkStream что-то досылал… и это вот прям нужно… я не встречал…

    Даже вот такой простой пример отлично работал.

    
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    
        public class TCPClientLight
        {
            public byte[] Connect(IPAddress IP, int Port, int WriteTimeout, int ReadTimeout, byte[] byteData, ref string MessageError)
            {
                byte[] numArray = (byte[])null;
    
                try
                {
                    IPAddress Address = IP;
                    TcpClient tcpClient = new TcpClient();
                    IAsyncResult asyncResult = tcpClient.BeginConnect(Address, Port, (AsyncCallback)null, (object)null);
                    WaitHandle asyncWaitHandle = asyncResult.AsyncWaitHandle;
    
                    if (!asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(Convert.ToDouble(ReadTimeout / 1000)), false))
                    {
                        tcpClient.Close();
                        throw new TimeoutException();
                    }
                    NetworkStream stream = tcpClient.GetStream();
                    stream.WriteTimeout = WriteTimeout;
                    stream.ReadTimeout = ReadTimeout;
                    stream.Write(byteData, 0, byteData.Length);
                    byteData = new byte[256];
                    int length = stream.Read(byteData, 0, byteData.Length);
                    numArray = new byte[length];
                    Array.Copy((Array)byteData, (Array)numArray, length);
    
                    // Прекратим ожидания, вызвав метод Close через дискриптор ожидания.
                    tcpClient.EndConnect(asyncResult);
                    asyncWaitHandle.Close();
                    tcpClient.Close();
    
                }
                catch (SocketException)
                {
                    MessageError = "Невозможно подключиться к " + IP + ":" + Port.ToString();
                }
                catch (TimeoutException)
                {
                    MessageError = "Превышено время подключения";
                }
                catch (FormatException)
                {
                    MessageError = "Неправильный формат IP адреса";
                }
                catch (ArgumentOutOfRangeException)
                {
                    MessageError = "Превышено значение порта";
                }
                catch (Exception ex)
                {
                    MessageError = ex.Message;
                }
    
                return numArray;
            }
        }
    
    #27174
    JurasskPark
    Участник

    Ну сделайте, пожалуйста! И я буду счастливым 🙂
    Не хочу я сидеть и считать размер пакеты под каждый вид команды…
    Около 40 видов разновидностей команд примерно получается… 🙁

    #27175
    manjey73
    Участник

    Да каких 40 разновидностей то ? у вас кодов запроса столько нет по документации.

    з.ы. насколько я понял, считать то и не надо.

    Покажите пару полных ответов, где у вас 4-х байтные переменные фигурируют

    #27176
    manjey73
    Участник

    Хотя не трудно догадаться, если N (3-й байт) не может физически быть больше 255, то в ответе либо N переменных, либо N/4 переменных + 2 байта CRC

    #27177
    manjey73
    Участник

    // Прием заголовка
    buf_in = new byte[3];
    Connection.Read(buf_in, 0, buf_in.Length, PollingOptions.Timeout, ProtocolFormat.Hex, out logText); //считать значение из порта
    Log.WriteLine(logText);

    if (buf_in[1] > 0x80)
    {
    // Ошибка, взвести флаг ошибки для дальнейшей обработки
    buf_in_res = new byte[3];
    readcnt = Connection.Read(buf_in_res, 0, buf_in_res.Length, PollingOptions.Timeout, ProtocolFormat.Hex, out logText); //считать значение из порта
    Log.WriteLine(logText);
    // Можно склеить оба буфера и вывести в лог одной строкой
    }
    else
    {
    buf_in_res = new byte[buf_in[2] + 2]; // Буфер тела ответа
    readcnt = Connection.Read(buf_in_res, 0, buf_in_res.Length, PollingOptions.Timeout, ProtocolFormat.Hex, out logText); //считать значение из порта
    Log.WriteLine(logText);
    // аналогично можно склеить два буфера и вывести лог одной строкой
    }

    Ну а потом от флага ошибки разор, либо ошибки, либо ответа в зависимости от запроса.

    #27180
    JurasskPark
    Участник

    Вот пример логов, скриншоты
    https://disk.yandex.ru/d/2raCFg10venzSQ

    #27181
    manjey73
    Участник

    FE 50 48 07 00 00 00 20 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 15 0C 16 00 00 13 0A 00 0C 00 00 00 CD 71

    и что вас тут смущает? 48h = 72 dec + 2 байта CRC
    думаю и в остальном будет так же.

    По примеру выше, вы даже можете читать в один заранее подготовленный буфер, только readcnt сделать разными и складывать их для понимания сколько всего байт.
    Учитывая что CRC расчитывается по Modbus пихать надо весь пакет вместе с CRC для проверки на 0, или минус два байта CRC и сверять два CRC

    Зная код запроса, вы знаете какой тип переменных у вас, 1-но байтовый или 4-х байтовый.
    Все., только начальная проверка на ответ об Ошибке

    #27182
    manjey73
    Участник

    90h = 144 dec и так далее

    Единственное, у вас по протоколу при запросах часа с текущего расчетного. Если зададите неправильно запрос, что получите в ответ? обрезок до текущего часа или Ошибку от прибора ?

    • Этот ответ был изменен 1 год, 2 месяца назад от manjey73.
    #27184
    manjey73
    Участник

    Connection.Read(buf_in, 0, buf_in.Length, PollingOptions.Timeout, ProtocolFormat.Hex, out logText);

    здесь 0 это смещение. измените команду так, что первые 3 байта читаются с 0 в буфер, следующее чтение со смещением например 3 и вместо buf_in.Length указывайте требуемое количество байт

    #27185
    JurasskPark
    Участник

    Меня смущает как рассчитать получаемый ответ в количестве байт. Проблема же «надо знать сколько получать», а не как обработать. ) Чтобы при получении пакета не выжидать время.

    • Этот ответ был изменен 1 год, 2 месяца назад от JurasskPark.
    #27187
    JurasskPark
    Участник

    Текущие значения:

    Тип параметра 0

    Количество регистров на чтение 127

    FE 51 00 00 00 00 00 00 8E 06

    FE 51 7F 18 01 17 12 10 0C 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B6 AF CC BE 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 5C 0C C8 C1 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E6 29

    Текущие значения:

    Тип параметра 2

    Количество регистров на чтение 37

    FE 51 02 00 00 00 00 00 8F E4

    FE 51 25 18 01 17 13 10 0C 0A 00 00 00 00 00 00 00 00 00 00 04 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C2 3C

    Текущие значения:

    Тип параметра 3

    Количество регистров на чтение 87

    FE 51 03 00 00 00 00 00 8E 35

    FE 51 57 18 01 17 14 10 0C 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9D 8E

    Текущие значения:

    Тип параметра 4

    Количество регистров на чтение 87

    FE 51 04 00 00 00 00 00 8F 82

    FE 51 57 18 01 17 15 10 0C 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C2 5B

    По какому условию понимать что при типе 0 количеством байт 127, при типе 2 — 37 байт, при типе 3 и 4 — 87?

    #27188
    manjey73
    Участник

    БЛИН — смотрите 3-й байт в полученных данных при чтении первых 3-х байт.

    Сперва вам надо прочитать первые три байта и проверить 2-й — если он больше 0x80 значит прибор ответил ошибкой и дочитать надо всего 3 байта, если меньше соответственно третий байт содержит количество байт данных + 2 байта CRC

    А вот по номеру запроса вы прекрасно знаете какие блоки данных у вас есть в принципе. Одно байтовые или 4-х байтовые.

    Уж 144 разделить на 4 не сложно и шагать потом по блоку данных и распихиваю что и куда нужно.

    #27189
    JurasskPark
    Участник

    Мы про разные вещи говорим.
    Вы думаете, что я не знаю как обрабатывать входящие данные, а я не хочу ждать Timeout и лишний код писать об вычислении этого readCNT чтобы выйти из while().

    • Этот ответ был изменен 1 год, 2 месяца назад от JurasskPark.
    #27191
    manjey73
    Участник

    Да не нужно вам условие…

    FE 51 7F — 7F = 127 байт, текущие данные 00

    ТипПар = 0…4 – это параметр, определяющий, какой набор текущих значений будут
    передан в ответе (см. ниже форматы ответов при различных значениях ТипПар).

    При 0, 1, 2 или 4 у вас разные наборы данных. Запрашиваете 0, соответственно знаете как разбирать, вам прилетело 127 байт

    Формат ответа при ТипПар = 0:
    СН 51h 7 + (NК х 12)
    1 байт 1 байт 1 байт

    127 — 7 байт = 120, 120 делим на 12 вы получили 10 наборов параметров

    Блин, у вас по протоколу простая математика, при этом 3-й байт вам говорит сколько байт данных в ответе, ну добавьте сюда 2 байта контрольной суммы и прочтите в ваш буфер со смещение в три байта все остальное после первого чтения…

Просмотр 15 сообщений - с 31 по 45 (из 70 всего)
  • Вы должны авторизироваться для ответа в этой теме.