From fd66ea89858da08124d7ae26c35a0bc6521c2631 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Thu, 15 Jun 2023 14:56:02 +0800 Subject: [PATCH] Misc Android: Add disconnect, re-pair and factory reset Qt: Show better log output Qt: Show message in statusbar(PC)/as toast(Android) Qt: Show the same MAC address only once Qt: Fix command for setting LDAC mode Qt: Add command for controlling playing state Qt: Fix logic for setting ambient sound volume --- Android/app/src/main/res/raw/cmd.json | 20 ++++- .../src/main/res/values-zh-rCN/strings.xml | 3 + Android/app/src/main/res/values/strings.xml | 3 + Qt/comm.cpp | 16 ++-- Qt/comm.h | 1 + Qt/commrfcomm.cpp | 6 ++ Qt/deviceform.cpp | 10 +++ Qt/deviceform.h | 1 + Qt/mainwindow.cpp | 28 +++++- Qt/mainwindow.h | 2 + Qt/mainwindow.ui | 3 +- Qt/w820nbplusform.cpp | 52 +++++++++++- Qt/w820nbplusform.h | 8 ++ Qt/w820nbplusform.ui | 85 ++++++++++++++++++- doc/KnownCommands/W820NB_Plus.txt | 47 ++++++++++ 15 files changed, 266 insertions(+), 19 deletions(-) diff --git a/Android/app/src/main/res/raw/cmd.json b/Android/app/src/main/res/raw/cmd.json index e34169e..a85d16e 100644 --- a/Android/app/src/main/res/raw/cmd.json +++ b/Android/app/src/main/res/raw/cmd.json @@ -35,10 +35,6 @@ "name": "cmd_game_off", "cmd": "0900" }, - { - "name": "cmd_poweroff", - "cmd": "CE" - }, { "name": "cmd_ldac_off", "cmd": "4900" @@ -50,5 +46,21 @@ { "name": "cmd_ldac_96k", "cmd": "4902" + }, + { + "name": "cmd_poweroff", + "cmd": "CE" + }, + { + "name": "cmd_disconnect", + "cmd": "CD" + }, + { + "name": "cmd_re_pair", + "cmd": "CF" + }, + { + "name": "cmd_factory_reset", + "cmd": "07" } ] \ No newline at end of file diff --git a/Android/app/src/main/res/values-zh-rCN/strings.xml b/Android/app/src/main/res/values-zh-rCN/strings.xml index df567f2..90005cb 100644 --- a/Android/app/src/main/res/values-zh-rCN/strings.xml +++ b/Android/app/src/main/res/values-zh-rCN/strings.xml @@ -19,4 +19,7 @@ LDAC: OFF LDAC: 48kHz/44.1kHz LDAC: 96kHz + 断开连接 + 恢复出厂设置 + 重新配对 \ No newline at end of file diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index 597003d..510b0f1 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -14,6 +14,9 @@ LDAC: 48kHz/44.1kHz LDAC: 96kHz Poweroff + Disconnect + Re-pair + Factory Reset Bluetooth adapter not found Bluetooth not open diff --git a/Qt/comm.cpp b/Qt/comm.cpp index 1eb8c98..ecfdeb8 100644 --- a/Qt/comm.cpp +++ b/Qt/comm.cpp @@ -11,11 +11,11 @@ Comm::Comm(QObject *parent) bool Comm::sendCommand(const QByteArray& cmd, bool isRaw) { - qDebug() << "send:" << cmd.toHex(); - if(isRaw) - return write(cmd); - else - return write(addChecksum(addPacketHead(cmd))); + QByteArray data = cmd; + if(!isRaw) + data = addChecksum(addPacketHead(cmd)); + qDebug() << "send:" << data.toHex(); + return write(data); } bool Comm::sendCommand(const char *hexCmd, bool isRaw) @@ -73,7 +73,8 @@ QByteArray Comm::checkValidity(QByteArray data) if(data[0] != '\xBB' && data[0] != '\xCC') { qDebug() << "error:" - << "unexpected head:" << (int)data[0]; + << "unexpected head:" << (int)data[0] + << "data:" << data.toHex(); return QByteArray(); } int expectedLength = (int)data[1] + 4; @@ -81,7 +82,8 @@ QByteArray Comm::checkValidity(QByteArray data) { qDebug() << "packet length error:" << "expected:" << expectedLength - << "received:" << data.length(); + << "received:" << data.length() + << "data:" << data.toHex(); return QByteArray(); } return removeCheckSum(data); diff --git a/Qt/comm.h b/Qt/comm.h index 6851add..8420f39 100644 --- a/Qt/comm.h +++ b/Qt/comm.h @@ -24,6 +24,7 @@ protected slots: signals: void newData(const QByteArray& data); void stateChanged(bool connected); + void showMessage(const QString& msg); }; #endif // COMM_H diff --git a/Qt/commrfcomm.cpp b/Qt/commrfcomm.cpp index 32ef062..117c792 100644 --- a/Qt/commrfcomm.cpp +++ b/Qt/commrfcomm.cpp @@ -31,7 +31,13 @@ void CommRFCOMM::onStateChanged() { QBluetoothSocket::SocketState state = m_socket->state(); if(state == QBluetoothSocket::ConnectedState) + { emit stateChanged(true); + emit showMessage(tr("Device Connected")); + } else if(state == QBluetoothSocket::UnconnectedState) + { emit stateChanged(false); + emit showMessage(tr("Device Disconnected")); + } } diff --git a/Qt/deviceform.cpp b/Qt/deviceform.cpp index da03098..748dd51 100644 --- a/Qt/deviceform.cpp +++ b/Qt/deviceform.cpp @@ -21,6 +21,8 @@ DeviceForm::DeviceForm(QWidget *parent) : ui->disconnectButton->setVisible(false); ui->searchStopButton->setVisible(false); + ui->deviceTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + connect(ui->searchRFCOMMButton, &QPushButton::clicked, this, &DeviceForm::onSearchButtonClicked); connect(ui->searchBLEButton, &QPushButton::clicked, this, &DeviceForm::onSearchButtonClicked); connect(ui->deviceTableWidget, &QTableWidget::cellClicked, this, &DeviceForm::onDeviceTableCellClicked); @@ -47,6 +49,7 @@ void DeviceForm::onSearchButtonClicked() return; } ui->deviceTableWidget->setRowCount(0); + m_shownDevices.clear(); #ifdef Q_OS_ANDROID getBondedTarget(m_isCurrDiscoveryMethodBLE); #endif @@ -63,6 +66,11 @@ void DeviceForm::onDeviceDiscovered(const QBluetoothDeviceInfo &info) { QString address = info.address().toString(); QString name = info.name(); + if(m_shownDevices.contains(address, Qt::CaseInsensitive)) + { + qDebug() << "dumplicate:" << address << name; + return; + } QTableWidget* deviceTable = ui->deviceTableWidget; int i; @@ -78,6 +86,7 @@ void DeviceForm::onDeviceDiscovered(const QBluetoothDeviceInfo &info) typeItem->setText(tr("RFCOMM")); typeItem->setData(Qt::UserRole, m_isCurrDiscoveryMethodBLE); deviceTable->setItem(i, 2, typeItem); + m_shownDevices.append(address); qDebug() << name @@ -172,6 +181,7 @@ void DeviceForm::getBondedTarget(bool isBLE) typeItem->setText(tr("RFCOMM")); typeItem->setData(Qt::UserRole, isBLE); deviceTable->setItem(i, 2, typeItem); + m_shownDevices.append(address); } } #endif diff --git a/Qt/deviceform.h b/Qt/deviceform.h index e2d17fe..cfddc29 100644 --- a/Qt/deviceform.h +++ b/Qt/deviceform.h @@ -35,6 +35,7 @@ private slots: QBluetoothDeviceDiscoveryAgent *m_discoveryAgent = nullptr; bool m_isCurrDiscoveryMethodBLE = false; + QStringList m_shownDevices; #ifdef Q_OS_ANDROID void getBondedTarget(bool isBLE); #endif diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 7f43b74..15c6295 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -5,6 +5,10 @@ #include #include #include +#include +#ifdef Q_OS_ANDROID +#include +#endif MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -15,6 +19,7 @@ MainWindow::MainWindow(QWidget *parent) m_deviceForm = new DeviceForm; m_w820p = new W820NBPlusForm; + ui->tabWidget->setTabText(0, m_w820p->windowTitle()); ui->tabWidget->insertTab(0, m_deviceForm, tr("Device")); ui->scrollAreaWidgetContents->layout()->addWidget(m_w820p); @@ -22,7 +27,9 @@ MainWindow::MainWindow(QWidget *parent) connect(m_deviceForm, &DeviceForm::disconnectDevice, this, &MainWindow::disconnectDevice); connect(this, &MainWindow::commStateChanged, m_deviceForm, &DeviceForm::onCommStateChanged); - +#ifdef Q_OS_ANDROID + ui->statusBar->hide(); +#endif QScroller::grabGesture(ui->scrollArea); // ui->scrollArea->horizontalScrollBar()->setEnabled(false); @@ -53,6 +60,8 @@ void MainWindow::connectToDevice(const QString& address, bool isBLE) connect(m_w820p, QOverload::of(&W820NBPlusForm::sendCommand), m_comm, QOverload::of(&Comm::sendCommand)); connect(m_comm, &Comm::newData, m_w820p, &W820NBPlusForm::processData); connect(this, &MainWindow::readSettings, m_w820p, &W820NBPlusForm::readSettings); + connect(m_comm, &Comm::showMessage, this, &MainWindow::showMessage); + connect(m_w820p, &W820NBPlusForm::showMessage, this, &MainWindow::showMessage); m_comm->open(address); } @@ -82,3 +91,20 @@ void MainWindow::on_readSettingsButton_clicked() emit readSettings(); } +void MainWindow::showMessage(const QString& msg) +{ +#ifdef Q_OS_ANDROID + QtAndroid::runOnAndroidThread([ = ] + { + QAndroidJniObject javaString = QAndroidJniObject::fromString(msg); + QAndroidJniObject toast = QAndroidJniObject::callStaticObjectMethod("android/widget/Toast", "makeText", + "(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;", + QtAndroid::androidActivity().object(), + javaString.object(), + jint(0)); // short toast + toast.callMethod("show"); + }); +#else + ui->statusBar->showMessage(msg, 2000); // 2000ms is the duration of short toast +#endif +} diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index e7bbb03..8fe8a35 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -23,6 +23,8 @@ class MainWindow : public QMainWindow MainWindow(QWidget *parent = nullptr); ~MainWindow(); +public slots: + void showMessage(const QString &msg); private: Ui::MainWindow *ui; diff --git a/Qt/mainwindow.ui b/Qt/mainwindow.ui index c685363..686a9e8 100644 --- a/Qt/mainwindow.ui +++ b/Qt/mainwindow.ui @@ -11,7 +11,7 @@ - MainWindow + mEDIFIER @@ -75,6 +75,7 @@ + diff --git a/Qt/w820nbplusform.cpp b/Qt/w820nbplusform.cpp index cd4eb41..e89a13b 100644 --- a/Qt/w820nbplusform.cpp +++ b/Qt/w820nbplusform.cpp @@ -75,11 +75,11 @@ void W820NBPlusForm::onCheckBoxInControlSettingsGroupClicked() void W820NBPlusForm::onBtnInLDACGroupClicked() { if(ui->LDACOFFButton->isChecked()) - emit sendCommand("C400"); + emit sendCommand("4900"); else if(ui->LDAC48kButton->isChecked()) - emit sendCommand("C401"); + emit sendCommand("4901"); else if(ui->LDAC96kButton->isChecked()) - emit sendCommand("C402"); + emit sendCommand("4902"); } void W820NBPlusForm::on_gameModeBox_clicked() @@ -112,6 +112,8 @@ void W820NBPlusForm::on_ASSetButton_clicked() QByteArray cmd = "\xC1\x03"; cmd += (char)(6 + ui->ASBox->value()); emit sendCommand(cmd); + // setting ambient sound volume triggers ambient sound mode + ui->noiseAmbientSoundButton->setChecked(true); } @@ -293,7 +295,7 @@ void W820NBPlusForm::processData(const QByteArray& data) void W820NBPlusForm::readSettings() { - const int interval = 200; + const int interval = 150; int i = 0; QTimer::singleShot(i, [ = ] {on_batteryGetButton_clicked();}); @@ -336,3 +338,45 @@ void W820NBPlusForm::on_firmwareGetButton_clicked() emit sendCommand("C6"); } + +void W820NBPlusForm::on_cmdSentButton_clicked() +{ + emit sendCommand(QByteArray::fromHex(ui->cmdEdit->text().toLatin1()), ui->cmdRawBox->isChecked()); +} + + +void W820NBPlusForm::on_PCPlayButton_clicked() +{ + emit sendCommand("C200"); +} + + +void W820NBPlusForm::on_PCPauseButton_clicked() +{ + emit sendCommand("C201"); +} + + +void W820NBPlusForm::on_PCVolUpButton_clicked() +{ + emit sendCommand("C202"); +} + + +void W820NBPlusForm::on_PCVolDownButton_clicked() +{ + emit sendCommand("C203"); +} + + +void W820NBPlusForm::on_PCPrevButton_clicked() +{ + emit sendCommand("C205"); +} + + +void W820NBPlusForm::on_PCNextButton_clicked() +{ + emit sendCommand("C204"); +} + diff --git a/Qt/w820nbplusform.h b/Qt/w820nbplusform.h index 04ff685..ffe7a80 100644 --- a/Qt/w820nbplusform.h +++ b/Qt/w820nbplusform.h @@ -25,6 +25,7 @@ public slots: signals: void sendCommand(const QByteArray& cmd, bool isRaw = false); void sendCommand(const char* hexCmd, bool isRaw = false); + void showMessage(const QString& msg); private slots: void onBtnInNoiseGroupClicked(); void onBtnInSoundEffectGroupClicked(); @@ -49,6 +50,13 @@ private slots: void on_batteryGetButton_clicked(); void on_MACGetButton_clicked(); void on_firmwareGetButton_clicked(); + void on_cmdSentButton_clicked(); + void on_PCPlayButton_clicked(); + void on_PCPauseButton_clicked(); + void on_PCVolUpButton_clicked(); + void on_PCVolDownButton_clicked(); + void on_PCPrevButton_clicked(); + void on_PCNextButton_clicked(); }; #endif // W820NBPLUSFORM_H diff --git a/Qt/w820nbplusform.ui b/Qt/w820nbplusform.ui index 6c1e6b3..b64bf55 100644 --- a/Qt/w820nbplusform.ui +++ b/Qt/w820nbplusform.ui @@ -7,7 +7,7 @@ 0 0 400 - 870 + 1070 @@ -17,7 +17,7 @@ - Form + W820NB Plus @@ -481,6 +481,87 @@ + + + + Play Control + + + + + + Vol+ + + + + + + + Vol- + + + + + + + Play + + + + + + + Pause + + + + + + + Prev + + + + + + + Next + + + + + + + + + + Send Command + + + + + + command(Hex) + + + + + + + Raw + + + + + + + Send + + + + + + diff --git a/doc/KnownCommands/W820NB_Plus.txt b/doc/KnownCommands/W820NB_Plus.txt index 5077a72..5421cf9 100644 --- a/doc/KnownCommands/W820NB_Plus.txt +++ b/doc/KnownCommands/W820NB_Plus.txt @@ -153,3 +153,50 @@ readData:BB0249012120 96k sendData:AA0249022110 readData:BB0249022121 + +-------- + +获取设备指纹 +sendData:AA01D8219C +readData:BB16D8xxxxyyyy +获取设备名 +sendData:AA01C9218D +readData:BB19C9xxxxyyyy +获取播放状态? +sendData:AA01C32187 +readData:BB02C303219C +获取? +sendData:AA0168212C +readData:BB026800213E +获取电池电量 +sendData:AA01D02194 +readData:BB02D04D21F3 +获取? +sendData:AA01D52199 +readData:BB02D50xyyyy + +获取游戏模式状态 +sendData:AA010820CC +readData:BB02080020DE +获取降噪模式+环境声音量 +sendData:AA01CC2190 +readData:BB03CC010621AA +获取MAC地址 +sendData:AA01C8218C +readData:BB07C8xxxxyyyy +获取固件版本 +sendData:AA01C6218A +readData:BB04C603000221A3 +键控 +sendData:AA02F00A21BF +readData:BB03F00A0621D7 +LDAC +sendData:AA0148210C +readData:BB024801211F +提示音量 +sendData:AA010520C9 +readData:BB02050720E2 +关机时间(变长结果) +sendData:AA01D32197 +readData:BB02D30021A9(无) +readData:BB03D3000521AF(5min)