Russian Qt Forum
Апрель 26, 2024, 23:49 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: побайтовая обработка QByteArray  (Прочитано 9405 раз)
FalloutST
Гость
« : Апрель 10, 2017, 15:07 »

Столкнулся с проблемой которую решить не в состоянии от банального незнания, нужен лучший возможный вариант.
---------------------------------------------
Есть функция принимающая данные с serial:
Код:
void MainWindow::readData()
{
    QByteArray bytearray;
    bytearray = serial->readAll();
    qDebug() << "<---- readData():" << bytearray;
    sp_parseRecievedData(bytearray);
}
Далее в процессе теста принимаемых данных понял что они поступают в рваном виде. Кроме того, в перерывах передачи могут поступать нулевые пакеты. Этот впрос вроде бы решен на стороне отсылателя но, такая возможность остается. Следовательно обработчик должен понимать, что ему поступает не полная инфа, да еще и труха которую обрабатывать не стоит вовсе.
Поступаемые данные пакетизированы. И отмечены стартовым и заканчивающим маркерами. Между маркеров "трухи" не встречал. Что меня радует. Теперь к делу.
В процессе обработки мне нужно побайтово разбирать поступаемые данные до момента формирования пакета. Алгоритм мне ясен но.
Поскольку из главного окна в котором и совершается соединение я запускаю другое окно с QTableView, в конченом итоге QTableView и должен получить данные из пакета.
Инициация просходит оттуда, отсылается команда и... надо обработать ответ.

Я вижу как запуск отдельного MVP c Qtread https://habrahabr.ru/post/246445/
Передавать процессу очередной кусок, который он будет разбирать и отсылать в QTableView. А по истечении времени он процесс будет останавливаться.

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

Записан
qate
Супер
******
Offline Offline

Сообщений: 1175


Просмотр профиля
« Ответ #1 : Апрель 10, 2017, 16:15 »

кто чтото понял ?
Записан
FalloutST
Гость
« Ответ #2 : Апрель 10, 2017, 16:38 »

Что не понятно, конкретика улучшит взаимопонимание. Хотя если не понятны слова которы я употребил, то тебе на форум где общаются на твоем родном языке. Обычно люди не понимающие просят конкретных разъяснений... Хотя некоторые олухи спамящие безсмысленными фразами этого умения лишены вовсе..
Что то меня понесло, а это рабы! Успеть бы нажать кнопку ответить пока могу дотянуться...

Это лирика, из нее вытекает просьба, такая же как и написанное тобой, если ее перевести в общечеловеческий русский.
Что именно не понятно то?
Записан
FalloutST
Гость
« Ответ #3 : Апрель 10, 2017, 16:45 »

тяжело читаемо тут?
Цитировать
Поскольку из главного окна в котором и совершается соединение я запускаю другое окно с QTableView, в конченом итоге QTableView и должен получить данные из пакета.
Инициация просходит оттуда, отсылается команда и... надо обработать ответ.
ок
есть
Код:
MainWindow : public QMainWindow
он заупускает serial
Код:
    QSerialPort *serial;
он же запускает другое окошко:
Код:
    HardwarePickDialog *hardware;
    hardware = new HardwarePickDialog;
    hardware->mw = this;

hardware должен получить пакеты пришедшие из serial
и засунуть в QtableView

void MainWindow::readData() запускается по 5-6 раз приняв очередную порцию данных ---> два пакета
кроме всего прочего не исключен прием треша = x00; возникающих на стороннем оборудовании исключительно между пакетами
« Последнее редактирование: Апрель 10, 2017, 16:48 от FalloutST » Записан
qate
Супер
******
Offline Offline

Сообщений: 1175


Просмотр профиля
« Ответ #4 : Апрель 10, 2017, 18:06 »

MainWindow "запускает" QSerialPort ? Правильнее говорить создает объект и подключается к сигналам
Что такое HardwarePickDialog никто не знает, ну да ладно - подключится к слотам и сигналам его и QSerialPort сможешь сам ?
Далее обрабатываешь в событии пакеты

В чем вопрос неясно ?
Хотябы минимальный пример набросай в компилируемый проект и приложи
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #5 : Апрель 10, 2017, 18:13 »

А можит у тебя окно слишкам маленькое и пакеты непамащаются?
папаробуй окна больше зделать
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Апрель 11, 2017, 10:02 »

Далее в процессе теста принимаемых данных понял что они поступают в рваном виде. Кроме того, в перерывах передачи могут поступать нулевые пакеты. Этот впрос вроде бы решен на стороне отсылателя но, такая возможность остается. Следовательно обработчик должен понимать, что ему поступает не полная инфа, да еще и труха которую обрабатывать не стоит вовсе.
Поступаемые данные пакетизированы. И отмечены стартовым и заканчивающим маркерами. Между маркеров "трухи" не встречал. Что меня радует.
Обычно пакеты имеют заголовок фиксированной длины в котором указана длина пакета. А принятые данные не начинают обрабатываться пока весь пакет не будет принят. В этом есть смысл: или весь пакет прошел или нет, на то он и пакет. А что у Вас за "жанглирование" - хз. Маркеры - а где гарантия что они не встретятся в теле пакета? Ну и неясно что Вы хотите. Так или иначе данные должны иметь какой-то известный Вам формат. Ну приняли пакет - передали его обработчику (возможно сигналом), обработчик отобразил принятое в таблице или что еще. В чем проблема-то?
Записан
titan83
Гость
« Ответ #7 : Апрель 11, 2017, 11:37 »

А можит у тебя окно слишкам маленькое и пакеты непамащаются?
папаробуй окна больше зделать
Пеши исчо. Атжег ровна. Даслез внатуре
)))))
Записан
FalloutST
Гость
« Ответ #8 : Апрель 11, 2017, 17:51 »

Вопрос заключается в том, что меня терзают сомнения, лучший ли метод я выбрал?
Создать новый поток и в им обрабатывать приходящую информацию до формирования пакета, который в свою очередь уже будет передавться в "увеличенные" окошки. Спасибо вездессущему духу повелительных наклонений заствляющим лучших мира сего вести себя как быдло не обременное знаниями.
Записан
FalloutST
Гость
« Ответ #9 : Апрель 11, 2017, 17:55 »

А можит у тебя окно слишкам маленькое и пакеты непамащаются?
папаробуй окна больше зделать
Пеши исчо. Атжег ровна. Даслез внатуре
)))))
Вот явный пример трех высших, дитя совкового пролитариата.
------------------------------
Как не странно такое проявляется только на русских форумах, где подобное обитает. Вопрос их не интересует. Как собственно и саморазвитие.
Записан
FalloutST
Гость
« Ответ #10 : Апрель 11, 2017, 18:02 »

по сути получается что конкретной кнопкой из hardware я сигналом запускаю из MainWindow обработчик: полагаю qobject и QTread и коннектами передаю инфу.. Надеюсь на человеческом выразился, сам тяжело понимаю о чем говорю, очень помогла бы литература в которой можно необходимые по данной теме знания получить.
Тогда у меня еще один вопрос, спустя скажем .... секунду или полторы терпения( поскольку в цепи может быть несколько устройств(два отвечают за 50мс)) мне нужно разорвать связи и удалить обработчик. QTimer подойдет для этого?
Записан
titan83
Гость
« Ответ #11 : Апрель 11, 2017, 18:24 »

Друг, ты очень категоричен. Несмотря на твой поток сознания, я пока так и не смог понять, чего же ты хочешь. Ты реально несвязно излагаешь мысли, это плохо в такой профессии, как программирование.
Поэтому саморазвитие пока не просматривается...  Буду осваивать телепатию)))
Весь процесс получения данных по serial interfaces абсолютно типичен, там сложно изобразить что-то новое.
Код:
bool QWshInstrument::openSerial()
{
    if (_serialPort.isOpen())
        return true;
    if (_settings->value("SERIALPORT/Portname").isEmpty()) {
        setLastError("Serial port file not specified (eWSH.conf)");
        return false;
    }
    _serialPort.setPortName(_settings->value("SERIALPORT/Portname"));
    if (_serialPort.open(QIODevice::ReadWrite)) {
        _serialPort.setBaudRate(static_cast<QSerialPort::BaudRate>(_settings->value("SERIALPORT/Baudrate").toInt()));
        _serialPort.setDataBits(static_cast<QSerialPort::DataBits>(_settings->value("SERIALPORT/Databits").toInt()));
        _serialPort.setStopBits(static_cast<QSerialPort::StopBits>(_settings->value("SERIALPORT/Stopbits").toInt()));
        _serialPort.setParity(static_cast<QSerialPort::Parity>(_parityNames.value(_settings->value("SERIALPORT/Parity"))));
        _serialPort.setFlowControl(static_cast<QSerialPort::FlowControl>(_flowControlNames.value(_settings->value("SERIALPORT/FlowControl"))));
        _serialPort.flush();
        connect(&_serialPort, &QSerialPort::readyRead, this, &QWshInstrument::onDataRecived);
        connect(this, &QWshInstrument::dataRecieved, this, &QWshInstrument::onRawDataRecieved);
        return true;
    }
    else {
        setLastError(_settings->value("SERIALPORT/Portname") + " return error - " + _serialPort.errorString());
        return false;
    }
}

void QWshInstrument::onDataRecived()
{
    if (_serialPort.bytesAvailable() > 0) {
        QByteArray newData = _serialPort.readAll();
        if (_reciveData)
            [b]_inputData.append(newData);[/b]
        else
            return;
        QByteArray eor(decode(xmlValue("EOR")).toLatin1());
        if (_inputData.indexOf(eor) > -1) {
            emit dataRecieved(QString(_inputData.left(_inputData.indexOf(eor)).replace('\0', ' ')).trimmed());
            emit endInstRead();
            _inputData.remove(0, _inputData.indexOf(eor) + eor.size());
        }
        if (_inputData.size() > 5000)
            _inputData.clear();
    }
}

При открытии порта я соединяю однократно свой слот и сигнал QSerialPort::readReady, а потом в своем слоте обрабатываю пришедшие данные. В этом случае прием пакета заканчивается по определенному символу (текстовый протокол), но я делал и таймер по приему для бинарных протоколов, тоже отлично работало.
Это все, не надо больше ничего, никаких thread тут не надо, просто вынеси обработку в отдельный класс, чтобы не засирать MainWindow и будет тебе счастье.
« Последнее редактирование: Апрель 12, 2017, 11:27 от titan83 » Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #12 : Апрель 12, 2017, 13:31 »

Что не понятно, конкретика улучшит взаимопонимание. Хотя если не понятны слова которы я употребил, то тебе на форум где общаются на твоем родном языке. Обычно люди не понимающие просят конкретных разъяснений... Хотя некоторые олухи спамящие безсмысленными фразами этого умения лишены вовсе..
Что то меня понесло, а это рабы! Успеть бы нажать кнопку ответить пока могу дотянуться...

Чувак, прекращай курить вещества... реально ни хрена не понятно было. А ты еще агрессивный какой-то.

titan83 правильно советует - никаких "окон" и в помине не надо, вынеси обработку в отдельный класс и будет счастье Улыбающийся
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
FalloutST
Гость
« Ответ #13 : Апрель 12, 2017, 14:09 »

Ребят спасибо, я агрюсь только на быдлятину. Простите за характер но если вы находите место шуткам, то почему бы и мне не поушутить.
Титан спасибо, на данный момент все так и реализованно. Но..
hardware - промежуточный диалог сбора данных с цепи устройств общающихся между собой по серилу. Позволяющий выбрать конкретную машинку для дальнейшей настройки.
serial - работает в MainWindow
дальше: принятые пакеты должны отсылаться конкретному диалогу их, диалогов, будет несколько: я уже реализовал обработку пакета теперь двигаюсь дальше и правда от НЕЗНАНИЯ, пришел сюда а не на англ яз форум, мне и на русском то тяжело объяснить.
Передача пакета прямо по сигналу readyRead вызовет ряд проблем, поскольку:
1) пакет, в 90% случаев, получаемый readAll() не полон.  Как результат мне надо будет обрабатывать рваные данные в кажой принимающей функции. На мой взляд лучше релизовать отдельный даже не класс а поток, дальее еще один довод.
2) Чехарда коннектов:
--->hardware запускаясь должен будет подключиться к readyRead и читать данные от туда
--->следующее за ним окно настройки "железяки" должно будет сделать тоже самое(ведь так?)
--->далее другое окошко скажем получения текущих данных опять должно будет рвать все эти связи и создавать свои...

ну лучше было бы создать отдельный обработчик который запускается из каждого отдельного "окошка"(прости господи за использование данного термина) с определенными параметрами: скажем в нутри пакета кроме количества данных будет указываться маркер ответа на запрос, по которому он будет отправлять пакеты обратно по "окошкам". Коих будет хероватуча(в априори).

Кроме всего прочего такой поток можно будет разрушить по таймеру. Ибо мне не надо слушать порт 24/7 без необходимости. Мне нужны только ответы на конкретные запросы.
Записан
titan83
Гость
« Ответ #14 : Апрель 12, 2017, 16:18 »

Ребят спасибо, я агрюсь только на быдлятину. Простите за характер но если вы находите место шуткам, то почему бы и мне не поушутить.
Титан спасибо, на данный момент все так и реализованно. Но..
hardware - промежуточный диалог сбора данных с цепи устройств общающихся между собой по серилу. Позволяющий выбрать конкретную машинку для дальнейшей настройки.
serial - работает в MainWindow
дальше: принятые пакеты должны отсылаться конкретному диалогу их, диалогов, будет несколько: я уже реализовал обработку пакета теперь двигаюсь дальше и правда от НЕЗНАНИЯ, пришел сюда а не на англ яз форум, мне и на русском то тяжело объяснить.
Передача пакета прямо по сигналу readyRead вызовет ряд проблем, поскольку:
1) пакет, в 90% случаев, получаемый readAll() не полон.  Как результат мне надо будет обрабатывать рваные данные в кажой принимающей функции. На мой взляд лучше релизовать отдельный даже не класс а поток, дальее еще один довод.
2) Чехарда коннектов:
--->hardware запускаясь должен будет подключиться к readyRead и читать данные от туда
--->следующее за ним окно настройки "железяки" должно будет сделать тоже самое(ведь так?)
--->далее другое окошко скажем получения текущих данных опять должно будет рвать все эти связи и создавать свои...

ну лучше было бы создать отдельный обработчик который запускается из каждого отдельного "окошка"(прости господи за использование данного термина) с определенными параметрами: скажем в нутри пакета кроме количества данных будет указываться маркер ответа на запрос, по которому он будет отправлять пакеты обратно по "окошкам". Коих будет хероватуча(в априори).

Кроме всего прочего такой поток можно будет разрушить по таймеру. Ибо мне не надо слушать порт 24/7 без необходимости. Мне нужны только ответы на конкретные запросы.
У тебя провал с архитектурой, вернее, ее просто нет.
Если ты нам продолжишь топить про свои "окошки", то я ограничусь нетленным советом от Racheengel и выйду из этого диспута.
Это ведь не Дельфи, где было так здорово наговнокодить 20000 строк в main.pas и радоваться тому что "работает же".
Итак:
--> 1) пакет, в 90% случаев, получаемый readAll() не полон.  Как результат мне надо будет обрабатывать рваные данные в кажой принимающей функции.
ШОК!!! Мы все работаем в такой же удручающей атмосфере. Нет никаких гарантий, что драйвер устройства пришлет тебе какой-то определенный размер кадра, поэтому кадр надо СОБИРАТЬ из "рваных" частей. В коде, который я тебе запостил (и который ты не читал), именно так и сделано. Я в слоте жду, пока не появится end-of-record character и после этого посылаю сигналом принятый кадр. И моему слоту глубоко похер, кто там дальше будет обрабатывать эту информацию дальше, хоть окошки, хоть потоки, хоть дядя Федя. Это называется слабая связность программы, в этот main power Qt - что есть сигналы и слоты.

--> На мой взляд лучше релизовать отдельный даже не класс а поток, дальее еще один довод.
Не стоит на твоем текущем уровне понимания связываться с потоками, без обид. Они здесь и не нужны, честно, я проверял.

--> --->hardware запускаясь должен будет подключиться к readyRead и читать данные от туда
--->следующее за ним окно настройки "железяки" должно будет сделать тоже самое(ведь так?)
--->далее другое окошко скажем получения текущих данных опять должно будет рвать все эти связи и создавать свои...
Забудь ты уже про свои окошки. Сначала делаешь модель, которая поставляет данные, а потом к модели привязываешь сколько хочешь "окошек".

--> ну лучше было бы создать отдельный обработчик который запускается из каждого отдельного "окошка"
Опять пройдусь по твоему уровню - не надо пытаться читать из serial port больше, чем из одного места.

--> скажем в нутри пакета кроме количества данных будет указываться маркер ответа на запрос, по которому он будет отправлять пакеты обратно по "окошкам"
Т.е. "протокол" еще и не имеет определенного формама? Ты его на ходу придумываешь, чтобы окошкам больше нравилось?

Итого: узнать что такое сигналы-слоты, узнать что такое MVC, начинать разработку с архитекутры, а не с "кодирования".
Ухх, я, пожалуй, выдохся в этой теме.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.06 секунд. Запросов: 22.