diff --git a/1D801Desktop.pro b/1D801Desktop.pro index 9488e53..04c20eb 100644 --- a/1D801Desktop.pro +++ b/1D801Desktop.pro @@ -14,11 +14,15 @@ CONFIG += c++17 SOURCES += \ bluetooth1d801.cpp \ + chart.cpp \ + chartview.cpp \ main.cpp \ mainwindow.cpp HEADERS += \ bluetooth1d801.h \ + chart.h \ + chartview.h \ mainwindow.h FORMS += \ diff --git a/bluetooth1d801.cpp b/bluetooth1d801.cpp index 32b01fd..ebe6425 100644 --- a/bluetooth1d801.cpp +++ b/bluetooth1d801.cpp @@ -8,13 +8,13 @@ Bluetooth1d801::Bluetooth1d801(QObject *parent):QObject(parent) { if (localDevice.isValid()) { //при создании экземпляра класса он подключается к свистку localDevice.powerOn(); localDeviceName = localDevice.name(); - qDebug() < remotes; remotes = localDevice.connectedDevices(); // если например наушники подключены и готовы выплевывает их адрес // с другими, например сопряженными не работает qDebug() <<"Подключенные устройства:"<start(); @@ -56,14 +56,38 @@ void Bluetooth1d801::stopDiscovery() } -void Bluetooth1d801::connectTo(const QBluetoothServiceInfo &service) +void Bluetooth1d801::connectTo(QListWidgetItem *item) { + // туду проверить, может уже подключен?? + + QBluetoothServiceInfo service = discoveredServices.value(item); + + + QBluetoothServiceInfo serviceToConnect = service; + qDebug() << "Connecting to service" << service.serviceName() //валим инфу в дебаг + << "on" << service.device().name(); + socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); //создание сокета + qDebug() << "Create socket"; + socket->connectToService(service); + connect(socket, &QBluetoothSocket::readyRead, this, &Bluetooth1d801::readSocket); + connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&Bluetooth1d801::connected)); + connect(socket, &QBluetoothSocket::disconnected, this, &Bluetooth1d801::disconnected); + connect(socket, &QBluetoothSocket::errorOccurred, this, &Bluetooth1d801::onSocketErrorOccurred); + qDebug() << "Мммм.. подключился... ))"; } void Bluetooth1d801::GetParam() { + if (!socket){ + qDebug()<< "Ты не создал подходящий сокет!!! Я не буду работать!!!"; + return; + } + QString message = "Get_Param"; + QByteArray text = message.toUtf8() + '\r' + '\n'; + socket->write(text); + // взвести коннект } @@ -109,20 +133,67 @@ void Bluetooth1d801::GetWaveEnv() void Bluetooth1d801::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) { + qDebug() << "Discovered service on" + << serviceInfo.device().name() << serviceInfo.device().address().toString(); + qDebug() << "\tService name:" << serviceInfo.serviceName(); + qDebug() << "\tDescription:" + << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); + qDebug() << "\tProvider:" + << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); + qDebug() << "\tL2CAP protocol service multiplexer:" + << serviceInfo.protocolServiceMultiplexer(); + qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); + const QBluetoothAddress address = serviceInfo.device().address(); + /* // если находятся много сервисов в одной железке, то названия не дублируются + for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { + if (info.device().address() == address) + return; // + } + */ + //! [serviceDiscovered] + QString remoteName; + if (serviceInfo.device().name().isEmpty()) + remoteName = address.toString(); + else + remoteName = serviceInfo.device().name(); + QListWidgetItem *item_p =new QListWidgetItem(QString::fromLatin1("%1 %2").arg(remoteName, serviceInfo.serviceName())); + discoveredServices.insert(item_p, serviceInfo); + + emit discoveryResult(item_p); + //qDebug() << "вот это работает в процедуре addItem" << item_p; // хах, так я определял что должно прелететь в слот родительского класса, ахах + //ui->listWidgetDevice->addItem(item); } void Bluetooth1d801::readSocket() { - + // return; // удалить 7.02.2024 - до этого подумать откуда он взялся + while (socket->canReadLine()) { + QByteArray line = socket->readLine().trimmed(); + qDebug() << line; + emit rawDataRecived(line); + } } + void Bluetooth1d801::connected() { - + emit connected(socket->peerName()); } void Bluetooth1d801::onSocketErrorOccurred(QBluetoothSocket::SocketError error) { + if (error == QBluetoothSocket::SocketError::NoSocketError) + return; + QMetaEnum metaEnum = QMetaEnum::fromType(); + QString errorString = socket->peerName()// + ' '_L1 + + metaEnum.valueToKey(static_cast(error)) + " occurred"; //_L1; + + emit socketErrorOccurred(errorString); +} + +void Bluetooth1d801::discoveryFinished() +{ + //emit discoveryFinishResult(discoveredServices); } diff --git a/bluetooth1d801.h b/bluetooth1d801.h index 3f0f237..2796ee9 100644 --- a/bluetooth1d801.h +++ b/bluetooth1d801.h @@ -12,9 +12,16 @@ #include +#include +#include +///прописать статус +/// перечисление статусов +/// сигнал статусИзменен + + class Bluetooth1d801 : public QObject { @@ -27,12 +34,11 @@ public: public slots: void startDiscovery(); //запускаем bluetooth поиск void stopDiscovery(); //прерываем его - void connectTo(QBluetoothServiceInfo); // подключится к сервису + void connectTo(QListWidgetItem *item); // подключится к сервису //команды для модуля в первородном виде void GetParam(); //получить параметры измерения void SetParam(); // запись параметров измерения - void GetMeas(); //Чтение измеренных значений void GetWave(); //Чтение временного сигнала виброускорения /виброскорости /виброперемещения void GetSpectrum();//Чтение спектра виброускорения /виброскорости /виброперемещения @@ -41,17 +47,23 @@ public slots: void GetSpectrumEnv(); //Чтение спектра огибающей виброускорения void GetWaveEnv();//Чтение сигнала огибающей виброускорения - private slots: void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo); //отрабатываю сигнал обнаруженного сервиса void readSocket(); //отработка сигнала прибывших данных void connected(); // отработка подключения void onSocketErrorOccurred(QBluetoothSocket::SocketError error);//отработка ошибки + void discoveryFinished(); signals: - void discoveryFinished(QMap); //возвращаем обнаруженные сервисы + void discoveryResult(QListWidgetItem *res_p); //возвращаем обнаруженные сервисы + //void MainWindow::addDiscoveryResult(QListWidgetItem *res_p) + //ui->listWidgetDevice->addItem(res_p); void rawDataRecived(QByteArray); // прилетели какие то данные! + void disconnected(); // отключилось устройство + void socketErrorOccurred(const QString &errorString); + void connected(const QString &name); // отработка подключения + private: QBluetoothSocket *socket = nullptr; // объект сокета для порта diff --git a/chart.cpp b/chart.cpp new file mode 100644 index 0000000..67bddba --- /dev/null +++ b/chart.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chart.h" + +#include +#include +#include + +Chart::Chart(QGraphicsItem *parent, Qt::WindowFlags wFlags) + : QChart(QChart::ChartTypeCartesian, parent, wFlags) +{ + // Seems that QGraphicsView (QChartView) does not grab gestures. + // They can only be grabbed here in the QGraphicsWidget (QChart). + grabGesture(Qt::PanGesture); + grabGesture(Qt::PinchGesture); +} + +//![1] +bool Chart::sceneEvent(QEvent *event) +{ + if (event->type() == QEvent::Gesture) + return gestureEvent(static_cast(event)); + return QChart::event(event); +} + +bool Chart::gestureEvent(QGestureEvent *event) +{ + if (QGesture *gesture = event->gesture(Qt::PanGesture)) { + auto pan = static_cast(gesture); + QChart::scroll(-(pan->delta().x()), pan->delta().y()); + } + + if (QGesture *gesture = event->gesture(Qt::PinchGesture)) { + auto pinch = static_cast(gesture); + if (pinch->changeFlags() & QPinchGesture::ScaleFactorChanged) + QChart::zoom(pinch->scaleFactor()); + } + + return true; +} +//![1] diff --git a/chart.h b/chart.h new file mode 100644 index 0000000..1d5de0c --- /dev/null +++ b/chart.h @@ -0,0 +1,25 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHART_H +#define CHART_H + +#include + +QT_FORWARD_DECLARE_CLASS(QGestureEvent) + +//![1] +class Chart : public QChart +//![1] +{ +public: + explicit Chart(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = {}); + +protected: + bool sceneEvent(QEvent *event); + +private: + bool gestureEvent(QGestureEvent *event); +}; + +#endif diff --git a/chartview.cpp b/chartview.cpp new file mode 100644 index 0000000..66c3ba3 --- /dev/null +++ b/chartview.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "chartview.h" + +#include + +ChartView::ChartView(QChart *chart, QWidget *parent) + : QChartView(chart, parent) +{ + setRubberBand(QChartView::RectangleRubberBand); +} + +bool ChartView::viewportEvent(QEvent *event) +{ + if (event->type() == QEvent::TouchBegin) { + // By default touch events are converted to mouse events. So + // after this event we will get a mouse event also but we want + // to handle touch events as gestures only. So we need this safeguard + // to block mouse events that are actually generated from touch. + m_isTouching = true; + + // Turn off animations when handling gestures they + // will only slow us down. + chart()->setAnimationOptions(QChart::NoAnimation); + } + return QChartView::viewportEvent(event); +} + +void ChartView::mousePressEvent(QMouseEvent *event) +{ + if (m_isTouching) + return; + QChartView::mousePressEvent(event); +} + +void ChartView::mouseMoveEvent(QMouseEvent *event) +{ + if (m_isTouching) + return; + QChartView::mouseMoveEvent(event); +} + +void ChartView::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_isTouching) + m_isTouching = false; + + // Because we disabled animations when touch event was detected + // we must put them back on. + chart()->setAnimationOptions(QChart::SeriesAnimations); + + QChartView::mouseReleaseEvent(event); +} + +//![1] +void ChartView::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Plus: + chart()->zoomIn(); + break; + case Qt::Key_Minus: + chart()->zoomOut(); + break; +//![1] + case Qt::Key_Left: + chart()->scroll(-10, 0); + break; + case Qt::Key_Right: + chart()->scroll(10, 0); + break; + case Qt::Key_Up: + chart()->scroll(0, 10); + break; + case Qt::Key_Down: + chart()->scroll(0, -10); + break; + default: + QGraphicsView::keyPressEvent(event); + break; + } +} diff --git a/chartview.h b/chartview.h new file mode 100644 index 0000000..de4d011 --- /dev/null +++ b/chartview.h @@ -0,0 +1,30 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CHARTVIEW_H +#define CHARTVIEW_H + +#include +#include + +//![1] +class ChartView : public QChartView +//![1] +{ +public: + ChartView(QChart *chart, QWidget *parent = nullptr); + +//![2] +protected: + bool viewportEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); +//![2] + +private: + bool m_isTouching = false; +}; + +#endif diff --git a/mainwindow.cpp b/mainwindow.cpp index bb3cac2..8bc8ca2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,32 +1,34 @@ #include "mainwindow.h" - #include "ui_mainwindow.h" -#include -#include - - - MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); -/* - if (localDevice.isValid()) { //при создании экземпляра класса он подключается к сввистку - localDevice.powerOn(); - localDeviceName = localDevice.name(); - qDebug() < remotes; - remotes = localDevice.connectedDevices(); // если например наушники подключены и готовы выплевывает их адрес - // с другими, например сопряженными не работает - qDebug() <bounded(20); + *series << p; // и приздяцим её в массив + } // и так по кругу + + chart = new Chart; //новый график + chart->addSeries(series); // закидываем ему массив точек // функция унаследована, есть еще removeAllSeries + //chart->setTitle("Zoom in/out example"); + chart->createDefaultAxes(); + chart->setAnimationOptions(QChart::SeriesAnimations); + chart->legend()->hide(); // скрыть легенду, в моем случае бесячую точку + auto chartView = new ChartView(chart); // на основе точек создаем обьект + chartView->setRenderHint(QPainter::Antialiasing); + // this->setCentralWidget(chartView);// эта шляпа растягивает chartview на весь окно + ui->horizontalLayout->addWidget(chartView); // добавляем виджет + //конец конструктора для графика } MainWindow::~MainWindow() @@ -35,145 +37,67 @@ MainWindow::~MainWindow() } -void MainWindow::on_pushButton_clicked() +void MainWindow::on_pushButtonSearch_clicked() { - QBluetoothServiceDiscoveryAgent *discoveryAgent = new QBluetoothServiceDiscoveryAgent(this); - - connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, - this, &MainWindow::serviceDiscovered); - connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, - this, &MainWindow::discoveryFinished); - connect(discoveryAgent, &QBluetoothServiceDiscoveryAgent::canceled, - this, &MainWindow::discoveryFinished); //странный коннект - слизал с бтчата (всмысле с указателями. Наверное это норм для динамических штук) - // начинаем поиск устройств - discoveryAgent->start(); - - if (discoveryAgent->isActive()) - discoveryAgent->stop(); - ui->listWidgetDevice->clear(); - // m_discoveryAgent->setUuidFilter(uuid); // подумай? может стоит впиздячить его на релизе - discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery); - ui->labelConnect->setText("Сейчас, я тебе что-нибудь найду"); + bt->startDiscovery(); // запускаем поиск + connect( // забираем найденые результаты + bt, &Bluetooth1d801::discoveryResult, + this, &MainWindow::addDiscoveryResult + ); } -void MainWindow::stopDiscovery() -{/* - if (m_discoveryAgent){ - m_discoveryAgent->stop(); - } -*/ -} - - -void MainWindow::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo) +void MainWindow::on_pushButtonConnect_clicked() { + qDebug()<< "Нажал кнопочку...)"; - qDebug() << "Discovered service on" - << serviceInfo.device().name() << serviceInfo.device().address().toString(); - qDebug() << "\tService name:" << serviceInfo.serviceName(); - qDebug() << "\tDescription:" - << serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString(); - qDebug() << "\tProvider:" - << serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString(); - qDebug() << "\tL2CAP protocol service multiplexer:" - << serviceInfo.protocolServiceMultiplexer(); - qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel(); - - - const QBluetoothAddress address = serviceInfo.device().address(); - /* // если находятся много сервисов в одной железке, то названия не дублируются - for (const QBluetoothServiceInfo &info : std::as_const(m_discoveredServices)) { - if (info.device().address() == address) - return; // - } - */ - //! [serviceDiscovered] - QString remoteName; - if (serviceInfo.device().name().isEmpty()) - remoteName = address.toString(); - else - remoteName = serviceInfo.device().name(); - QListWidgetItem *item =new QListWidgetItem(QString::fromLatin1("%1 %2").arg(remoteName, serviceInfo.serviceName())); - discoveredServices.insert(item, serviceInfo); - ui->listWidgetDevice->addItem(item); - //! [serviceDiscovered] } -void MainWindow::discoveryFinished() -{ - ui->labelConnect->setText("Я сделал всё, что мог"); -} - -void MainWindow::deviceDiscovered(const QBluetoothDeviceInfo &device) -{ - ui->listWidgetDevice->addItem(device.name()); - qDebug() << "Found new device:" << device.name() << '(' << device.address().toString() << ')'; -} - -void MainWindow::on_pushButton_2_clicked() -{ - auto items = ui->listWidgetDevice->selectedItems(); - if (items.size()) { - QListWidgetItem *item = items[0]; - QBluetoothServiceInfo service = discoveredServices.value(item); - qDebug() << "Connecting to service" << service.serviceName() //валим инфу в дебаг - << "on" << service.device().name(); - socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); //создание сокета - qDebug() << "Create socket"; - socket->connectToService(service); - connect(socket, &QBluetoothSocket::readyRead, this, &MainWindow::readSocket); - connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&MainWindow::connected)); - connect(socket, &QBluetoothSocket::disconnected, this, &MainWindow::disconnected); - connect(socket, &QBluetoothSocket::errorOccurred, this, &MainWindow::onSocketErrorOccurred); - qDebug() << "ConnectToService done"; - ui->labelConnect->setText("Похоже получилось подключится"); - } -} - - -void MainWindow::readSocket() -{ - if (!socket) - return; - - while (socket->canReadLine()) { - QByteArray line = socket->readLine().trimmed(); - qDebug() << line; - ui->listWidgetResponse->addItem(line.toHex()); - emit messageReceived(socket->peerName(), - QString::fromUtf8(line.constData(), line.length())); - } -} - -void MainWindow::onSocketErrorOccurred(QBluetoothSocket::SocketError error) -{ - if (error == QBluetoothSocket::SocketError::NoSocketError) - return; - - QMetaEnum metaEnum = QMetaEnum::fromType(); - QString errorString = socket->peerName()// + ' '_L1 - + metaEnum.valueToKey(static_cast(error)) + " occurred"; //_L1; - - emit socketErrorOccurred(errorString); -} - -void MainWindow::connected() -{ - emit connected(socket->peerName()); -} - - void MainWindow::on_pushButtonGetParam_clicked() { - if (!socket){ - qDebug()<< "Ты не создал подходящий сокет!!! Я не буду работать!!!"; - return; - } - QString message = "Get_Param"; - QByteArray text = message.toUtf8() + '\r' + '\n'; - - socket->write(text); } +void MainWindow::addDiscoveryResult(QListWidgetItem *res_p) +{ + ui->listWidgetDevice->addItem(res_p); +} + +void MainWindow::addRawData(QByteArray data) +{ + ui->listWidgetResponse->addItem(data.toHex()); +} + +void MainWindow::on_listWidgetDevice_itemDoubleClicked(QListWidgetItem *item) +{ + if(!bt){ + qDebug() << "телега пошла вперед лошади, сливай воду"; + return; + } + + bt->connectTo(item); + connect( // забираем сырые ответы + bt, &Bluetooth1d801::rawDataRecived, + this, &MainWindow::addRawData + ); +} + + + + +void MainWindow::on_pushButtonClearCharts_clicked() +{ + chart->removeAllSeries(); +} + + +void MainWindow::on_pushButton_clicked() +{ + auto series = new QLineSeries; //QLineSeries - делает массив точек для графиков. умеет append например + for (int i = 0; i < 500; i++) { //иииии вцикле + QPointF p(i, QRandomGenerator::global()->bounded(100)); // делаем точку c координатами в конструкторе + *series << p; // и приздяцим её в массив + } // и так по кругу + chart->addSeries(series); +} + diff --git a/mainwindow.h b/mainwindow.h index dbbeac0..d7be7e8 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -3,22 +3,20 @@ #include #include -#include -#include -#include -#include -#include #include #include - - -#include -#include -#include -#include -#include - #include +#include + +#include + + +#include "chart.h" +#include "chartview.h" +#include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -38,30 +36,28 @@ public: ~MainWindow(); private slots: - void on_pushButton_clicked(); - void deviceDiscovered(const QBluetoothDeviceInfo &device); - void on_pushButton_2_clicked(); - void stopDiscovery(); - void serviceDiscovered(const QBluetoothServiceInfo &serviceInfo); - void discoveryFinished(); - void readSocket(); - void connected(); - void onSocketErrorOccurred(QBluetoothSocket::SocketError error); + void on_pushButtonSearch_clicked(); + void on_pushButtonConnect_clicked(); void on_pushButtonGetParam_clicked(); + void addDiscoveryResult(QListWidgetItem *res_p); + void addRawData(QByteArray); + + void on_listWidgetDevice_itemDoubleClicked(QListWidgetItem *item); + + void on_pushButtonClearCharts_clicked(); + + void on_pushButton_clicked(); + signals: - void messageReceived(const QString &sender, const QString &message); - void connected(const QString &name); - void disconnected(); - void socketErrorOccurred(const QString &errorString); private: Ui::MainWindow *ui; - - QBluetoothSocket *socket = nullptr; - QBluetoothLocalDevice localDevice; QString localDeviceName; - QMap discoveredServices; + Bluetooth1d801 *bt; + + Chart* chart; + QLineSeries* series; }; #endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui index 0341e29..7bab1bc 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -488,7 +488,7 @@ MainWindow - + 20 @@ -501,7 +501,7 @@ Поиск устройств - + 150 @@ -682,6 +682,43 @@ Ответы + + + + 590 + 20 + 681 + 301 + + + + + + + + 590 + 350 + 151 + 31 + + + + Очисить график + + + + + + 770 + 350 + 201 + 31 + + + + Постороить случайный + +