Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.75/40: Рейтинг темы: голосов - 40, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 30.09.2017
Сообщений: 182

Недопонимание QByteArray

10.01.2018, 11:14. Показов 9096. Ответов 47

Студворк — интернет-сервис помощи студентам
У меня происходит соединение по UDP, всё происходит на моём компьютере. Есть программа, которая отправляет строчки раз в секунду

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
UdpServer::UdpServer(QWidget* pwgt /*=0*/) : QTextEdit(pwgt)
{
    setWindowTitle("UdpServer");
 
    m_pudp = new QUdpSocket(this);
 
    QTimer* ptimer = new QTimer(this);
    ptimer->setInterval(1000);
    ptimer->start();
    connect(ptimer, SIGNAL(timeout()), SLOT(slotSendDatagram()));
}
 
// ----------------------------------------------------------------------
void UdpServer::slotSendDatagram()
{
    QByteArray baDatagram;
    QDataStream out(&baDatagram, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_7);
    QString string = "some amazing things";
    append("Sent:" + string);
    out << string;
    m_pudp->writeDatagram(baDatagram, QHostAddress::LocalHost, 1234);
}
На приёмнике происходит следующее

C++ (Qt)
1
2
3
4
socket = new QUdpSocket(this);
 
        socket->bind(1234);
     connect(socket, SIGNAL(readyRead()), SLOT(read()));
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void MainWidget::read()
{
 
 
 
    QByteArray baDatagram;
 
    if (socket->hasPendingDatagrams())
    {
 
        QHostAddress *address = new QHostAddress;
 
        baDatagram.resize(socket->pendingDatagramSize());
        socket->readDatagram(baDatagram.data(), baDatagram.size(), address);
        qDebug() << baDatagram;
.........
}
и вот тут у меня череда вопросов, которые могут показаться вам дуратскими, но с которыми я не могу разобраться
почему в дебаге получается вот такое
\x00\x00\x00&\x00s\x00o\x00m\x00""e\x00 \x00""a\x00m\x00""a\x00z\x00i\x00n\x00g\ x00 \x00t\x00h\x00i\x00n\x00g\x00s

в какой форме вообще он выводит этот Байт Аррей? Я думал, что х будет означать Hex форму, но ничего подобного
я вижу здесь свои буквы, но к чему, например \x00 (при qDebug() << baDatagram.toHex() он дописывает дополнительные 00 перед каждой буквой, почему он это делает????)
Откуда иногда берутся вот эти кавычки ""
Почему перед строкой помимо всего прочего он дописывает это "\x00\x00\x00&"

Заранее спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.01.2018, 11:14
Ответы с готовыми решениями:

QByteArray
Добрый день! Каким образом проще считать из файла с 5 по 10 байт? Два последних байта считываю так: QString...

QByteArray и UCS2-BE
Есть юникод строки в виде hex QString(&quot;042304320430043604300435043C044B04390020041A&quot;); насколько я понял это в UCS-2BE кодировке. ...

QByteArray в int
Привет всем! Ситуация такая: с контроллера через COM передаю unsigned long int ловлю в Qt QByteArray так: QByteArray byte; ...

47
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 06:48
Студворк — интернет-сервис помощи студентам
insite2012, я просто больше учусь программировать микроконтроллеры на С, но периодически приходится иметь дело с C++, поэтому много не знаю и обращаюсь сюда за помощью, чтобы понимающие люди подсказали в каком направлении искать решение.
Так будет правильно?
C++ (Qt)
1
2
3
        DataRes = static_cast<unsigned char> (Data[0]);
        DataRes <<= 8;
        DataRes += static_cast<unsigned char> (Data[1]);
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 06:53
Можно одной строкой.
C++ (Qt)
1
DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1])
1
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 09:02
insite2012, Avazart, С преобразование данных теперь все нормально, спасибо за помощь, можете подсказать по поводу проверки bytesAvailable?
Есть функция в которой идет прием данных:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
void MainWindow::sockReady()
{
    if (socket->waitForConnected(500))
    {        
        socket->waitForReadyRead(500);
        Data = socket->readAll();
        DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]);   // Transform 2 bytes of Data to unsigned shorts DataRes
        QString DataString = QString::number(DataRes);
        ui->Data_label->setText(DataString);
        qDebug()<<Data;
        qDebug()<<"DataRes:"<<DataRes;
    }
}
Если в ней же организовать проверку bytesAvailable это будет корректно или так лучше не делать?
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void MainWindow::sockReady()
{
    if (socket->waitForConnected(500))
    {        
        //Getting number of Bytes Available
        qint64 bytesAvailable = socket->bytesAvailable();
        qDebug() << "Bytes available: " << bytesAvailable;
        ui->label_BytesAvailable -> setText(QString::number(bytesAvailable));
 
        //Receive TCP data
        if (bytesAvailable < expected)   // expected равняется 2м
            return;
        socket->waitForReadyRead(500);
        const QByteArray Data = socket->read(expected);
        DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]);   // Transform 2 bytes of Data to unsigned shorts DataRes
        QString DataString = QString::number(DataRes);
        ui->Data_label->setText(DataString);
        qDebug()<<Data;
        qDebug()<<"DataRes:"<<DataRes;
    }
}
Во время тестирования кода BytesAvailable выводится как 4, т.е. двойная порция данных доступна сокету

Добавлено через 29 минут
Просто у меня помимо соединения TCP, извлечения и преобразования данных, идут еще функции сравнения полученных данных, создания строки, записи в файл и тд, все это выполнять в void MainWindow::sockReady() я думаю будет неправильно, но вопрос тогда куда передать данные из void MainWindow::sockReady() чтобы в дальнейшим с ними работать?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 10:25
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
можете подсказать по поводу проверки bytesAvailable?
Не думаю что это так уж необходимо, по правде. Вы можете в слоте, который соединен с сигналом readyRead() считывать все что пришло, и там уже по размеру проверять, все ли считано или нет. И я не пойму, зачем вы используете методы waitFor...(). Сокеты отлично работают в асинхронном режиме, а если вам нужно остановиться в определенной точке кода и дождаться, когда сокет отработает асинхронную операцию по приему, используете QTimer и QEventLoop. Я так делаю при работе с последовательным портом и Bluetooth сокетом, поскольку код не может исполняться дальше, пока данные не считаны и не проверены на их корректность.
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
у меня помимо соединения TCP, извлечения и преобразования данных, идут еще функции сравнения полученных данных, создания строки, записи в файл и тд, все это выполнять в void MainWindow::sockReady() я думаю будет неправильно
Конечно нет. Явное нарушение single-responsibility principle, принципа единственной ответственности. Вам нужен класс, принимающий (и отсылающий, если требуется) данные через сокет. Что за данные, как их интерпретировать, проверять, корректны ли они или нет-не его дело. Его ответственность-отослать что нужно и принять ответ. А уж интерпретацию данных, их преобразование и прочее нужно выделить в отдельный класс, который будет отвечать именно за это.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 10:47
insite2012,
Цитата Сообщение от insite2012 Посмотреть сообщение
И я не пойму, зачем вы используете методы waitFor...()
Этот код я накидал довольно давно, видимо взял из какого-то примера по подключению TCP. Сейчас пришлось вернуться и добавить много новых функций в программу.
Про принцип единственной ответственности я понял, просто большие пробелы в знании Qt и C++.
Логика работы программы заключается в том, чтобы отослать данные на микроконтроллер, он их принял, в ответ начал отсылать данные с АЦП, программа их приняла, преобразовала, записала в файл. Параллельно еще работают таймеры и тд.
Вот код, который используется сейчас, вроде отсылает и принимает все как надо, теперь буду пробовать добавлять новые функции в программу
Файл mainwindow.cpp
Кликните здесь для просмотра всего текста

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
//-----------------------------------------------------------------
//Includes
#include <QString>
#include <QByteArray>
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Variables and arrays
unsigned short DataRes = 0;
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    // TCP connection
    socket = new QTcpSocket(this);
    connect(socket,SIGNAL(readyRead()),this,SLOT(sockReady()));
    connect(socket,SIGNAL(disconnected()),this,SLOT(sockDisc()));
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
MainWindow::~MainWindow()
{
    delete ui;
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::on_ConnectToServer_Button_clicked()
{
    socket->connectToHost("192.168.1.195",80);
    ui->Connected_label->setText("Connected");        // Output "Connected" to lebel
    socket->write("Connected");                       // Send "Connected"
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::sockDisc()
{
    socket->deleteLater();
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::sockReady()
{
    if (socket->waitForConnected(500))
    {        
        socket->waitForReadyRead(500);
        Data = socket->readAll();
        DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]);   // Transform 2 bytes of Data to unsigned shorts DataRes
        QString DataString = QString::number(DataRes);
        ui->Data_label->setText(DataString);
        qDebug()<<Data;
        qDebug()<<"DataRes:"<<DataRes;
    }
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::on_SendHi_Button_clicked()
{
    socket->write("Hi!!!");
}
 
void MainWindow::on_Send5_Button_clicked()
{
    socket->write("5");
}
 
void MainWindow::on_Send7_Button_clicked()
{
    socket->write("7");
}
 
void MainWindow::on_DisconnetcWithServer_Button_clicked()
{
    socket->deleteLater();
    ui->Connected_label->setText("Disconnected");     // Output "Disconnected" to lebel
}
 
void MainWindow::on_SendLine_Button_clicked()
{
    DataSendLineEdit = ui->SendData_lineEdit->text();
    DataSend = DataSendLineEdit.toUtf8();
    socket->write(DataSend);
}
//-----------------------------------------------------------------

Можете подсказать как уйти от waitFor? Ситуация примерно такая же как и у вас с последовательным портом: ждем данные, как только пришли, отрабатываем их преобразование, ждем следующую порцию данных
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 11:16
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Можете подсказать как уйти от waitFor?
Попробую в процессе дня накидать вам простой пример по вашему коду.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 11:26
insite2012, хорошо, спасибо, жду
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 12:47
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Логика работы программы заключается в том, чтобы отослать данные на микроконтроллер
DmitryDDDD, уточните ТЗ, данные от ПК на мк нужно передать только один раз, а потом идет только прием, либо это необходимо делать периодически, по команде от пользователя?
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 13:04
insite2012,
На МК настроено несколько каналов 12 битного АЦП (для отладки я пока взял только 1 канал). АЦП несколько раз в секунду измеряет состояние входов, DMA извлекает данные. Дальше в зависимости от входящего сигнала с ПК на МК, данные АЦП усредняются (в 10, в 100 или в 600 раз), Еще из входящих сигналов для МК это запуск передачи данных и их остановка.
Итого для МК входящие сигналы: запуск АЦП, остановка, значение во сколько раз усреднять данные. Сигналы могут быть посланы от пользователя в процессе работы МК.
Теперь что делает программа на ПК: создает файл (csv) единоразово, при запуске. Дальше по приходу данных от МК они преобразуются сначала в 16-битные, затем сравниваются с массивом значений (здесь происходит подмена принятых данных значением из массива, т.к. принимаем мы величину АЦП, а затем меняем ее на идентичную ей величину температуры), и записываются в csv файл в виде строки первым аргументом которой идет время приема обработанной партии данных. Как-то так.
С похожим вопросом я уже обращался на форум но только там прием был по UART, ну и мной было нарушен принцип единственной ответственности, поэтому сейчас хочется сделать все более правильно с точки зрения построения кода, но пока не многим я владею в Qt.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
20.08.2020, 13:41
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
void MainWindow::sockReady()
{
 if (socket->waitForConnected(500))
 { 
 socket->waitForReadyRead(500);
 Data = socket->readAll();
 DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]); // Transform 2 bytes of Data to unsigned shorts DataRes
 QString DataString = QString::number(DataRes);
 ui->Data_label->setText(DataString);
 qDebug()<<Data;
 qDebug()<<"DataRes:"<<DataRes;
 }
}
В слоте такие вещи как
C++
1
2
socket->waitForConnected(500))
socket->waitForReadyRead(500);
неверно использовать. В общем берите книгу смотрите примере и разбирайтесь с сигналами и слотами.

Добавлено через 3 минуты
C++ (Qt)
1
2
3
4
5
6
7
8
void MainWindow::sockReady()
{
    while(socket->bytesAvailable()>2)
    {       
 // ...   читаем 2 байта  socket->read(2) 
 
    }
}
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 13:55
DmitryDDDD, уточните еще момент: допустим, мы соединились с мк через сокет, послали команду на передачу. Что дальше, нам в той же точке ждать ответа, или можно послать команду и выйти из метода, а потом в вызывающем коде ждать? То есть суть вопроса в том, как организована связь: запрос-обязательный ответ или просто запрос, а дальше ожидаем, и по приходу реагируем?
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
20.08.2020, 14:05
insite2012, я думаю реагируем по прихожу. Может из моего объяснения что-то не так понятно, в сообщениях выше я имел ввиду, что например послали мы команду на усреднение, мк ее принял и шлет нам данные в зависимости от величины усреднения например раз в секунду. Сидим получаем данные, потом захотелось нам получать данные не раз в секунду, а раз в минуту, отсылаем новую команду на усреднение и мк уже накапливает больше данных, усредняем их, и результат отправляет раз в минуту.
Т.е. запрос, получаем поток данных, как понадобилось делаем новый запрос, опять получаем поток
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
20.08.2020, 14:43
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Т.е. запрос, получаем поток данных, как понадобилось делаем новый запрос, опять получаем поток
Так ваша ситуация еще проще. В моем случае запросы шли потоком один за другим, а каждый последующий был в связи с последним полученным ответом.
Вам можно тогда не особо заморачиваться.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#ifndef TCPCONNECTOR_H
#define TCPCONNECTOR_H
 
#include <QtCore>
#include <QObject>
#include <QtNetwork>
 
class TcpConnector : public QObject
{
    Q_OBJECT
private:
    QTcpSocket* m_pTcpSocket;
    QString m_address;
    int m_port;
    QByteArray m_buffer;
public:
    explicit TcpConnector(QObject *parent = nullptr);
    void init(const QString& address, int port);
    void connect();
    void disconnect();
 
public slots:
    void slotMcuCommand(const QByteArray& command);
private slots:
    void slotReadyRead();
    void slotError(const QAbstractSocket::SocketError socketError);
 
signals:
    void signalConnected();
    void signalDisconnected();
    void signalDataAvailable(const QString& data);
    void signalError(const QString& message);
};
 
#endif // TCPCONNECTOR_H
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "TcpConnector.h"
 
 
TcpConnector::TcpConnector(QObject *parent) : QObject(parent), m_pTcpSocket(nullptr)
{
 
}
 
void TcpConnector::init(const QString &address, int port)
{
    m_address=address;
    m_port=port;
}
 
void TcpConnector::connect()
{
    m_pTcpSocket=new QTcpSocket(this);
    QObject::connect(m_pTcpSocket, SIGNAL(connected()),
                     this, SIGNAL(signalConnected()));
    QObject::connect(m_pTcpSocket, SIGNAL(disconnected()),
                     this, SIGNAL(signalDisconnected()));
    QObject::connect(m_pTcpSocket, SIGNAL(readyRead()),
                     this, SLOT(slotReadyRead()));
    QObject::connect(m_pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
                     this, SLOT(slotError(QAbstractSocket::SocketError)));
    m_pTcpSocket->connectToHost(QHostAddress(m_address),m_port);
 
}
 
void TcpConnector::disconnect()
{
    if(m_pTcpSocket && m_pTcpSocket->state()==QTcpSocket::ConnectedState){
        m_pTcpSocket->disconnectFromHost();
    }
}
 
void TcpConnector::slotMcuCommand(const QByteArray &command)
{
    if(m_pTcpSocket && m_pTcpSocket->state()==QTcpSocket::ConnectedState){
        //write data into socket to send in to mcu for start/stop/command mcu
        m_pTcpSocket->write(command.data(), command.size());
 
    }
}
 
void TcpConnector::slotReadyRead()
{
    m_buffer.clear();
    m_buffer=m_pTcpSocket->readAll();
 
    if(!m_buffer.isEmpty() && m_buffer.size()>=2){
        emit signalDataAvailable(m_buffer);
    }
    else{
        emit signalError(QObject::tr("No answer from mcu"));
    }
}
 
void TcpConnector::slotError(const QAbstractSocket::SocketError socketError)
{
    emit signalError(QObject::tr("Socket error"));
}
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
21.08.2020, 13:03
insite2012, Спасибо за предоставленный код, очень помогает разобраться в чем-то, долго копался в нем, хотел в том виде как он есть перенести на свою программу, но вылетали ошибки, потом решил перенести его частично, так как прослеживается аналогия, вот результат, прошу посмотреть, может указать на ошибки, которые здесь есть:
mainwindow.h
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QTcpSocket>
#include <QMessageBox>
 
#include <QtCore>
#include <QObject>
#include <QtNetwork>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
    QTcpSocket* socket;
    QByteArray Data;
    QByteArray DataSend;          // Data for sending
    QString DataSendLineEdit;     // SendDatalineEdit Data
 
public slots:
    void sockReady();
    void sockDisc();
 
private slots:
    void on_ConnectToServer_Button_clicked();
 
    void on_SendHi_Button_clicked();
 
    void on_Send5_Button_clicked();
 
    void on_Send7_Button_clicked();
 
    void on_DisconnetcWithServer_Button_clicked();
 
    void on_SendLine_Button_clicked();
 
    void slotError(const QAbstractSocket::SocketError socketError);
 
private:
    Ui::MainWindow *ui;
 
signals:
    void signalConnected();
    void signalDataAvailable(const QString& data);
    void signalError(const QString& message);
};
 
#endif // MAINWINDOW_H


mainwindow.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
//-----------------------------------------------------------------
//Includes
#include <QString>
#include <QByteArray>
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Variables and arrays
unsigned short DataRes = 0;
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    // TCP connection
    // Не стал создавать отдельную функцию connect, связал сигналы и слоты здесь
    socket = new QTcpSocket(this);
    connect(socket, SIGNAL(connected()), this, SIGNAL(signalConnected()));
    connect(socket,SIGNAL(readyRead()),this,SLOT(sockReady()));
    connect(socket,SIGNAL(disconnected()),this,SLOT(sockDisc()));
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotError(QAbstractSocket::SocketError)));
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
MainWindow::~MainWindow()
{
    delete ui;
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::on_ConnectToServer_Button_clicked()   // функция соединения с сервером
{
    socket->connectToHost("192.168.1.195",80);
    socket->write("Connected");                       // Send "Connected"
    ui->Connected_label->setText("Connected");        // Output "Connected" to lebel
 
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::sockDisc()
{
    if(socket && socket->state()==QTcpSocket::ConnectedState)
    {
        socket->disconnectFromHost();
        socket->deleteLater(); // добавил в Ваш код из своего функцию удаления сокета при закрытии
    }
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::sockReady()
{
// Закоментированный код это то, что было до
//    while(socket->bytesAvailable()>2)
//    {
//        qint64 bytesAvailable1 = socket->bytesAvailable();
//        qDebug() << "Bytes available1: " << bytesAvailable1;
//        //Data = socket->readAll();
//        Data = socket->read(2);
//        DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]);   // Transform 2 bytes of Data to unsigned shorts DataRes
//        QString DataString = QString::number(DataRes);
//        ui->Data_label->setText(DataString);
//        qDebug()<<Data;
//        qDebug()<<"DataRes:"<<DataRes;
//        qint64 bytesAvailable2 = socket->bytesAvailable();
//        qDebug() << "Bytes available2: " << bytesAvailable2;
//    }
 
    // Это код уже с добавлением Вашего
    Data.clear();
    qint64 bytesAvailable1 = socket->bytesAvailable();
    qDebug() << "Bytes available1: " << bytesAvailable1;
    Data=socket->read(2);
    if(!Data.isEmpty() && Data.size()>=2)
    {
        emit signalDataAvailable(Data);
        DataRes = static_cast<quint8> (Data[0])*0x100+static_cast<quint8> (Data[1]);   // Transform 2 bytes of Data to unsigned shorts DataRes
        QString DataString = QString::number(DataRes);
        ui->Data_label->setText(DataString);
        qDebug()<<"Data:"<<Data;
        qDebug()<<"DataRes:"<<DataRes;
        qint64 bytesAvailable2 = socket->bytesAvailable();
        qDebug() << "Bytes available2: " << bytesAvailable2;
    }
    else
    {
        emit signalError(QObject::tr("No answer from mcu"));
    }
}
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
void MainWindow::slotError(const QAbstractSocket::SocketError socketError)
{
    emit signalError(QObject::tr("Socket error"));
}
//-----------------------------------------------------------------
 
// Код функции передачи данных на МК я оставил по нажатию кнопок
//-----------------------------------------------------------------
void MainWindow::on_SendHi_Button_clicked()
{  
    if(socket && socket->state()==QTcpSocket::ConnectedState)
    {
        socket->write("Hi!!!");    // Есть ли смысл проверять условие if или можно сразу отправлять строку?
    }
}
 
void MainWindow::on_Send5_Button_clicked()
{
    if(socket && socket->state()==QTcpSocket::ConnectedState)
    {
        socket->write("5");
    }
}
 
void MainWindow::on_Send7_Button_clicked()
{
    if(socket && socket->state()==QTcpSocket::ConnectedState)
    {
        socket->write("7");
    }
}
 
void MainWindow::on_DisconnetcWithServer_Button_clicked()
{
    socket->deleteLater();
    ui->Connected_label->setText("Disconnected");     // Output "Disconnected" to lebel
}
 
void MainWindow::on_SendLine_Button_clicked()
{
    DataSendLineEdit = ui->SendData_lineEdit->text();
    DataSend = DataSendLineEdit.toUtf8();
    socket->write(DataSend);
}
//-----------------------------------------------------------------


Некоторые вопросы есть в комментариях, еще такой момент: компилятор говорит, что параметр socketError не используется
Так же вопрос, у меня везде идет отправка данных в виде строки socket->write("5");
У Вас я увидел что-то похожее на возможность передачи буфера или целочисленого значения
C++ (Qt)
1
m_pTcpSocket->write(command.data(), command.size());
Как организовать передачу буфера? Т.е. передать в command.data() и command.size() параметры какого-либо созданного массива значений? Если можно, хочется услышать критику кода выше, чтобы знать допущенные ошибки
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.08.2020, 14:30
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
компилятор говорит, что параметр socketError не используется
Да, там просто нужно было через switch перебирать значения перечисления и выводить нужную ошибку. Лень было все прописывать))
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
увидел что-то похожее на возможность передачи буфера или целочисленого значения
Сокет унаследован от QIODevice, а у этого класса есть одна из таких перегрузок, которая принимает аргументами указатель на const char и размер данных. Можно и сразу QByteArray туда передать, без размера.
По критике кода.
1. Вывод об успешном соединении нужно делать не сразу после вызова connectToHost () (может, сокет и не сможет соединиться), а в слоте, подключенном к сигналу connected()
2. Удаление сокета (deleteLater()) можно подключить к его же сигналу disconnected().
3. Я так понимаю, ваш проект простой, хотя я бы рекомендовал выносить всю работу с сокетом в отдельный класс, и не мешать код интерфейса непосредственно с работой сокета. Так будет удобнее. Можно вообще написать весь класс в консоли, там его и отладить, а интерфейс уже прикрутить потом.
0
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
22.08.2020, 07:16
insite2012,
Цитата Сообщение от insite2012 Посмотреть сообщение
3. Я так понимаю, ваш проект простой, хотя я бы рекомендовал выносить всю работу с сокетом в отдельный класс, и не мешать код интерфейса непосредственно с работой сокета. Так будет удобнее. Можно вообще написать весь класс в консоли, там его и отладить, а интерфейс уже прикрутить потом.
Да там ничего особенного нет, несколько управляющих команд, поток данных, который обрабатываем и упаковываем в файл, по сути с моими минимальными знаниями можно это сейчас собрать из того, что есть и оно работать будет, но я думаю это будет не правильным решением, пихать все в кучу, и прислушаюсь к Вашему совету разделения интерфейса, сокета и тд. Ибо если проект будет усложняться, буду ловить ошибки. Попробую пока накидать программку, в которой было бы все организовано правильно, но просто трудности в том, как связать GUI и сокет. Т.е. например есть функции сокета (прием, отправка и тд), есть кнопка по нажатию которой мы берем данные например из строки LineEdit и передаем их в функцию отправки сообщения. Ну или взаимодействие между классом сокета и классом обработки данных (полученных от сокета). Надо себе ликбез провести.
Я же могу добавить ваши файлы cpp и h в свой проект не пересоздавая его, затем обращаться к функциям сокета, или в настройках при создании надо что-то указывать?
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
22.08.2020, 08:35
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
трудности в том, как связать GUI и сокет
Да нет там никаких трудностей. Мыслите по аналогии-сокет это тоже класс. Как вы с ним взаимодействуете? Вызывая его методы для этого. И тут все также, никаких отличий нет.
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
Я же могу добавить ваши файлы cpp и h в свой проект не пересоздавая его
Конечно, почему нет. Как я ранее говорил, мне вообще удобнее сначала создать консольку, отладить все рабочие классы в ней, а потом создать проект с GUI, добавить туда уже готовые отлаженные классы и прикрутить к ним интерфейс.
1
4 / 4 / 0
Регистрация: 12.11.2018
Сообщений: 511
22.08.2020, 09:52
insite2012, Хорошо, спасибо за помощь),
Цитата Сообщение от insite2012 Посмотреть сообщение
Как вы с ним взаимодействуете?
Пока что с трудом)
Я думаю мне сначала надо немного почитать по Qt и C++, да и взяться за код. Тогда уже создам новую тему и обязательно обращусь за помощью)
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
22.08.2020, 10:12
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
думаю мне сначала надо немного почитать по Qt и C++
Почему же нет. Возьмите того же Макса Шлее, хорошая книга. Допускаю что с первого раза поймете не все, но прочитав ее раза два-три (и не просто прочитав, а выполнив все примеры что там предоставлены) к вам придет просветление.
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,876
22.08.2020, 10:32
Цитата Сообщение от DmitryDDDD Посмотреть сообщение
DataRes = ((Data[0]<<8)||(Data[1]));
почему ИЛИ то логическое (||) ?
для объединения нужно арифметическое (|)
C++ (Qt)
1
DataRes = ((Data[0]<<8)|(Data[1]));
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.08.2020, 10:32

Структуру в QByteArray
Как перевести произвольную структуру в QByteArray и обратно? struct MyStruct { int a; float b; QString str; };

QImage и QByteArray
Приветствую Для того, чтобы сохранить фотографию в БД, я ее из QImage перегоняю в QByteArray и далее сохраняю в Blob поле в БД Вот...

Запись в QByteArray
Здравствуйте, у меня такой вопрос. Допустим я веду счётчик: 1,2,3,4 и т.д. до 65535. В 16-ричном виде эти числа, соответственно...

QByteArray и память
Доброй ночи) Короче есть код который записывает кусок одного файла в другой qds.readRawData(buf,...

Qt C++ QByteArray QFile
Здравствуйте! Возникла проблема: имеется файл, в нем данные записываются следующим образом: первые байт - младший байт, второй байт -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru