I'm developing an cross plattform Application in Qt Creator, which has the exercise to control a device via Classic Bluetooth. I have a communication protocol. FIRST: I can connect to device and write Data to it with BluetoothSocket. If I put the startMotor() function into the socketConnected SLOT after beepBuzzor() command then it works fine and I get state() connected.
My problem is if I switch the page in my Application on Android and click on the "start motor" button, I get the state() unconnected, but I am still connected to the device because the LED on the device shows connected. My app does not crash. I think the problem is in the line with socket->connectToService(...), but I'm unsure what to change. The beepBuzzor command works fine, startMotor command too. But if I call the function after successfully connectToService() it does not work because the state is unconnected.
BluetoothManager::BluetoothManager(QObject *parent) : QObject(parent)
{
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
}
void BluetoothManager::startDiscovery()
{
// Check if Bluetooth is available on this device
if (localDevice.isValid()) {
qDebug() << "Bluetooth is available on this device";
//Turn BT on
localDevice.powerOn();
// Make it visible to others
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
//Read local device name & address
qDebug() << "Local Device:" << localDevice.name() << "(" << "Address:" << localDevice.address() << ")";
// Create a discovery agent and connect to its signals
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(discoveryAgent, SIGNAL(finished()), this, SLOT(deviceDiscoverFinished()));
// Start a discovery
// Trick: da es kein DiscoveryTimer für Classic gibt, suchen wir nach LE devices, da BT121 BLE unterstützt.
// Die Verbindung erfolgt jedoch über RFCOMM sobald man sich mit dem Gerät verbindet.
discoveryAgent->setLowEnergyDiscoveryTimeout(5000);
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
qDebug() << "Device discover started";
}
else
{
qDebug() << "Bluetooth is not available on this device";
}
}
//SLOT for the finish of device Discovery
void BluetoothManager::deviceDiscoverFinished()
{
qDebug() << "Device discover finished";
listOfDevices = discoveryAgent->discoveredDevices();
qDebug() << "Found new devices:";
for (int i = 0; i < listOfDevices.size(); i++)
{
//Q_OS_IOS / MAC do not need here cuz the run is on android device, delete later
//We do not find galileo device on MacBook
#if defined (Q_OS_IOS) || defined (Q_OS_MAC)
// On MacOS and iOS we get no access to device address,
// only unique UUIDs generated by Core Bluetooth.
qDebug() << "getting address from deviceUuid()" << listOfDevices.at(i).name().trimmed()
<< " ( " << listOfDevices.at(i).deviceUuid().toString().trimmed() << " ) ";
setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).deviceUuid().toString().trimmed() + ")");
#else
qDebug() << listOfDevices.at(i).name().trimmed()
<< " ("
<< listOfDevices.at(i).address().toString().trimmed()
<< ")";
setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).address().toString().trimmed() + ")");
#endif
}
}
/**
* In GUI (QML) user select a device with index i.
* Create a new socket, using Rfcomm protocol to communicate
*/
void BluetoothManager::deviceSelected(int i)
{
selectedDevice = listOfDevices.at(i);
#if defined (Q_OS_IOS) || defined (Q_OS_MAC)
qDebug() << "User select a device: " << selectedDevice.name() << " ("
<< selectedDevice.deviceUuid().toString().trimmed() << ")";
#else
qDebug() << "User select a device: " << selectedDevice.name() << " ("
<< selectedDevice.address().toString().trimmed() << ")";
#endif
if (localDevice.pairingStatus(selectedDevice.address())== QBluetoothLocalDevice::Paired)
{
qDebug() << "Pairing is allready done";
}
else
{
qDebug() << "Not paired. Please do pairing first for communication with device!";
}
selecDevAdress = selectedDevice.address();
connectToSvc();
//Connect SIGNALS with SLOTS
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError)));
connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketRead()));
connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged()));
}
void BluetoothManager::connectToSvc()
{
qDebug() << "Create socket";
//socket->connectToService(selecDevAdress, QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);
//static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB"));
socket->connectToService(selectedDevice.address(), QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);
//Also works with this line instead of the two above (with declaration of serviceUuid)
//socket->connectToService(QBluetoothAddress(selectedDevice.address()),QBluetoothUuid(QBluetoothUuid::SerialPort));
socket->open(QIODevice::ReadWrite);
socket->openMode();
}
//SLOT wenn Socket verbunden ist
void BluetoothManager::socketConnected()
{
//qDebug() << ("Connected to: "+socket->peerAddress().toString() +":"+socket->peerPort());
qDebug() << ("Connected to: "+socket->peerAddress().toString());
qDebug() << "Socket connected";
qDebug() << "Local: "
<< socket->localName()
<< socket->localAddress().toString()
<< socket->localPort();
qDebug() << "Peer: "
<< socket->peerName()
<< socket->peerAddress().toString()
<< socket->peerPort();
//Do "beep" sound commando after succesfull connection to Galileo device
beepBuzzor();
}
/**
* Socket disconnected.
* Delete socket, free the memory.
*/
//SLOT für Verbindungsabbruch von Socket
void BluetoothManager::socketDisconnected()
{
qDebug() << "Socket disconnected";
socket->deleteLater();
}
void BluetoothManager::socketError(QBluetoothSocket::SocketError error)
{
qDebug() << "Socket error: " << error;
}
void BluetoothManager::socketStateChanged()
{
int socketState = socket->state();
if(socketState == QAbstractSocket::UnconnectedState)
{
qDebug() << "unconnected";
}
else if(socketState == QAbstractSocket::HostLookupState)
{
qDebug() << "host lookup";
}
else if(socketState == QAbstractSocket::ConnectingState )
{
qDebug() << "connecting";
}
else if(socketState == QAbstractSocket::ConnectedState)
{
qDebug() << "connected";
}
else if(socketState == QAbstractSocket::BoundState)
{
qDebug() << "bound";
}
else if(socketState == QAbstractSocket::ClosingState)
{
qDebug() << "closing";
}
else if(socketState == QAbstractSocket::ListeningState)
{
qDebug() << "listening";
}
}
// SLOT when data ready on bluetooth socket
void BluetoothManager::socketRead()
{
qDebug() << "socketRead()";
QByteArray recievedData = socket->readAll();
emit dataRecieved(recievedData);
}
/**
* Get a string with device info
*/
const QString &BluetoothManager::device() const
{
return deviceInfo;
}
void BluetoothManager::setDevice(const QString &newDevice)
{
if (newDevice != deviceInfo) {
deviceInfo = newDevice;
emit deviceChanged();
}
}
void BluetoothManager::beepBuzzor()
{
QByteArray beep;
beep.append(QByteArray::fromRawData("\x04\x00\x09\xD0\x07\x32\x00", 7));
command(beep);
}
void BluetoothManager::startMotor()
{
qDebug() << "startMotor slot";
if(socket->state() == QBluetoothSocket::UnconnectedState){
qDebug() << "Socket Unconnected";
}
else{
qDebug() << "Socket Unonnected";
}
socketStateChanged();
//command(start);
}
void BluetoothManager::command(QByteArray &cmdBuf)
{
socket->write(cmdBuf);
}
Related
I have a problem with reading characteristic using Bluetooth Low Energy Qt api. The device I'm communicating with is a Decawave DWM1001 module. I was following the tutorial from the documentation. I managed to connect to the device, read and creates it's service successfully. The device has "network node service" with UUID: 680c21d9-c946-4c1f-9c11-baa1c21329e7, which I'm trying to read characteristics from. I call QLowEnergyController::connectToDevice() method, it finds the service and I create a QLowEnergyService object for it, named nodeService.
void BluetoothConnector::serviceDiscovered(const QBluetoothUuid &newService)
{
qDebug() << "Service discovered: " << newService.toString();
if (newService == QBluetoothUuid(nodeServiceUUID)) {
nodeService = controller->createServiceObject(QBluetoothUuid(nodeServiceUUID), this);
if (nodeService) {
qDebug() << "Node service created";
connect(nodeService, &QLowEnergyService::stateChanged, this, &BluetoothConnector::serviceStateChanged);
connect(nodeService, &QLowEnergyService::characteristicChanged, this, &BluetoothConnector::updateCharacteristic);
//connect(nodeService, &QLowEnergyService::descriptorWritten, this, &BLTest::confirmedDescriptorWrite);
nodeService->discoverDetails();
} else {
qDebug() << "Node service not found.";
}
}
}
nodeService is created successfully (I get "Node service created" log), then I connect the signals and slots for the service and then call discoverDetails() on nodeService. The serviceStateChanged() slot looks like this:
void BluetoothConnector::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
if (newState == QLowEnergyService::DiscoveringServices) {
qDebug() << "Discovering services";
} else if (newState == QLowEnergyService::ServiceDiscovered) {
qDebug() << "Service discovered";
const QLowEnergyCharacteristic networkIdChar = nodeService->characteristic(QBluetoothUuid(networkIdUUID));
const QLowEnergyCharacteristic dataModeChar = nodeService->characteristic(QBluetoothUuid(dataModeUUID));
const QLowEnergyCharacteristic locationChar = nodeService->characteristic(QBluetoothUuid(locationUUID));
if (networkIdChar.isValid() && dataModeChar.isValid() && locationChar.isValid()) {
auto idValue = networkIdChar.value();
auto modeValue = dataModeChar.value();
auto locValue = locationChar.value();
qDebug() << "Network ID: " << idValue;
qDebug() << "Mode: " << modeValue;
qDebug() << "Location: " << locValue;
auto notificationDesc = locationChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if (notificationDesc.isValid()) {
qDebug() << "Notification desc valid";
nodeService->writeDescriptor(notificationDesc, QByteArray::fromHex("0100"));
}
} else {
qDebug() << "Characteristic invalid";
}
}
}
I get the "Discovering services" log and after that the app hangs for a bit and then I get:
"Cannot read descriptor (onDescReadFinished 3): \"{00002902-0000-1000-8000-00805f9b34fb}\" \"{3f0afd88-7770-46b0-b5e7-9fc099598964}\" \"org.freedesktop.DBus.Error.NoReply\" \"Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.\""
"LowEnergy controller disconnected"
"Aborting onCharReadFinished due to disconnect"
It can't read the 00002902-0000-1000-8000-00805f9b34fb which is CCCD descriptor for the 3f0afd88-7770-46b0-b5e7-9fc099598964 characteristic (vendor specific).
Can't figure out what's wrong and why it can't read characteristics from the device. Do I need to do something else to make it work?
Thanks.
---UPDATE---
BluetoothConnector class:
#include "bluetoothconnector.h"
#include <QTimer>
BluetoothConnector::BluetoothConnector(QObject *parent) : QObject(parent)
{
configureDiscoveryAgent();
}
void BluetoothConnector::scan()
{
agent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}
void BluetoothConnector::connectToDevice(QString &addr)
{
auto it = std::find_if(devices.begin(), devices.end(),
[&] (const QBluetoothDeviceInfo& d) { return d.address().toString() == addr; });
if (it == devices.end())
return;
device = *it;
controller = QLowEnergyController::createCentral(device, this);
connect(controller, &QLowEnergyController::serviceDiscovered, this, &BluetoothConnector::serviceDiscovered);
connect(controller, &QLowEnergyController::discoveryFinished, this, &BluetoothConnector::serviceScanDone);
connect(controller, static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
this, [this](QLowEnergyController::Error error) {
Q_UNUSED(error);
qDebug() << "Controller error: " << error;
emit controllerError();
});
connect(controller, &QLowEnergyController::connected, this, [this]() {
qDebug() << "Controller connected. Search services...";
controller->discoverServices();
});
connect(controller, &QLowEnergyController::disconnected, this, [this]() {
qDebug() << "LowEnergy controller disconnected";
});
controller->connectToDevice();
}
void BluetoothConnector::configureDiscoveryAgent()
{
agent = new QBluetoothDeviceDiscoveryAgent(this);
agent->setLowEnergyDiscoveryTimeout(5000);
connect(agent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothConnector::addDevice);
connect(agent, static_cast<void (QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error),
this, &BluetoothConnector::scanError);
connect(agent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothConnector::scanFinished);
connect(agent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &BluetoothConnector::scanFinished);
}
void BluetoothConnector::addDevice(const QBluetoothDeviceInfo &info)
{
if (!devices.contains(info)) {
qDebug() << "Found device: " << info.name();
devices.append(info);
emit deviceFound(info);
}
}
void BluetoothConnector::scanError(QBluetoothDeviceDiscoveryAgent::Error error)
{
qDebug() << "Scan error: " << error;
}
void BluetoothConnector::scanFinished()
{
emit scanFinishedSignal();
}
void BluetoothConnector::serviceDiscovered(const QBluetoothUuid &newService)
{
qDebug() << "Service discovered: " << newService.toString();
if (newService == QBluetoothUuid(nodeServiceUUID)) {
nodeService = controller->createServiceObject(QBluetoothUuid(nodeServiceUUID), this);
qDebug() << "State: " << nodeService->state();
if (nodeService) {
qDebug() << "Node service created";
connect(nodeService, &QLowEnergyService::stateChanged, this, &BluetoothConnector::serviceStateChanged);
connect(nodeService, &QLowEnergyService::characteristicChanged, this, &BluetoothConnector::updateCharacteristic);
connect(nodeService, &QLowEnergyService::characteristicWritten, this, &BluetoothConnector::characteristicWritten);
connect(nodeService, QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error),
[=](QLowEnergyService::ServiceError newError){ qDebug() << newError; });
//connect(nodeService, &QLowEnergyService::descriptorWritten, this, &BLTest::confirmedDescriptorWrite);
nodeService->discoverDetails();
} else {
qDebug() << "Node service not found.";
}
}
}
void BluetoothConnector::serviceScanDone()
{
qDebug() << "Services scan done";
}
void BluetoothConnector::characteristicWritten(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
qDebug() << "Characteristic written: " << info.name();
}
void BluetoothConnector::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
qDebug() << "State changed: " << newState;
if (newState == QLowEnergyService::ServiceDiscovered) {
qDebug() << "Service discovered";
const QLowEnergyCharacteristic networkIdChar = nodeService->characteristic(QBluetoothUuid(networkIdUUID));
const QLowEnergyCharacteristic dataModeChar = nodeService->characteristic(QBluetoothUuid(dataModeUUID));
const QLowEnergyCharacteristic locationChar = nodeService->characteristic(QBluetoothUuid(locationUUID));
if (networkIdChar.isValid() && dataModeChar.isValid() && locationChar.isValid()) {
auto idValue = networkIdChar.value();
auto modeValue = dataModeChar.value();
auto locValue = locationChar.value();
qDebug() << "Network ID: " << idValue;
qDebug() << "Mode: " << modeValue;
qDebug() << "Location: " << locValue;
auto notificationDesc = locationChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if (notificationDesc.isValid()) {
qDebug() << "Notification desc valid";
nodeService->writeDescriptor(notificationDesc, QByteArray::fromHex("0100"));
}
} else {
qDebug() << "Characteristic invalid";
}
}
}
void BluetoothConnector::updateCharacteristic(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
if (info.uuid() == QBluetoothUuid(networkIdUUID)) {
qDebug() << "Update ID: " << value;
} else if (info.uuid() == QBluetoothUuid(dataModeUUID)) {
qDebug() << "Update mode: " << value;
} else if (info.uuid() == QBluetoothUuid(locationUUID)) {
qDebug() << "Update location: " << value;
}
}
I think, the problem is located on the remote side (your GATT server).
Check the QLowEnergyService::error() and QLowEnergyService::charcteristicWritten() signal and see if you get any response.
What kind of Bluetooth stack you are use on the remote side?
Might be, you don't have the rights to change the CCCD due to a implementation failure. Please check the implementation on the remote side.
I'm developing a Qt app which need to read data from weight scale model and can't quite understand how exactly the Bluetooth Low Energy works and how to implement it in Qt.
I have a UC-352BLE weight scale which uses BLE to send data. What I want to achieve is this:
After initial pairing the scale with my Raspberry Pi on which my app is running, when the scale sends data (it does it automatically when you take a measurement), my app receive it. For example I have a blood pressure monitor which uses normal Bluetooth and here it's easy. In my app, I create a QBluetoothServer and call its listen() method. Then when the (already paired) device sends a measurement, it connects with my app automatically, then I create QBluetoothSocket and read the data. But with the scale and it's BLE it seems that you can't do it that way. I tried to follow the Qt documentation on this and right now I just have to manually press the button which connects to the scale when it's sending the data. And every time it connects to the device it discovers it's characteristics and services etc. Don't know if I can do it so the app automatically receives a connection and reads a data when the scale sends a measurement. And even when I try to connects like that sometimes it connects and sometimes don't (I get Unknown error form QLowEnergyController::Error when connecting). Here is what I already have:
Bletest::Bletest(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Bletest)
{
ui->setupUi(this);
if (localDevice.isValid()) {
localDevice.powerOn();
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
connect(&localDevice, &QBluetoothLocalDevice::deviceConnected, this, &Bletest::deviceConnected);
connect(&localDevice, &QBluetoothLocalDevice::deviceDisconnected, this, &Bletest::deviceDisconnected);
connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, this, &Bletest::pairingFinished);
}
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &Bletest::addDevice);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &Bletest::scanFinished);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &Bletest::scanFinished);
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}
Bletest::~Bletest()
{
delete ui;
}
// Local device slots
void Bletest::deviceConnected(const QBluetoothAddress &address)
{
qDebug() << address.toString() << " connected";
}
void Bletest::deviceDisconnected(const QBluetoothAddress &address)
{
qDebug() << address.toString() << " disconnected";
}
void Bletest::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
{
}
// Agent slots
void Bletest::addDevice(const QBluetoothDeviceInfo &device)
{
if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
if (device.name().contains("352")) {
bleDevice = device;
qDebug() << "Found: " + device.name() + "\t" + device.address().toString();
}
}
}
void Bletest::scanFinished()
{
qDebug() << "Devices scan finished";
}
///////////
void Bletest::on_connectButton_clicked()
{
controller = QLowEnergyController::createCentral(bleDevice, this);
connect(controller, &QLowEnergyController::serviceDiscovered, this, &Bletest::serviceDiscovered);
connect(controller, &QLowEnergyController::discoveryFinished, this, &Bletest::serviceScanFinished);
connect(controller, static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
this, [this](QLowEnergyController::Error error) {
qDebug() << "Cannot connect to device: " + QString::number(error);
});
connect(controller, &QLowEnergyController::connected, this, [this]() {
qDebug() << "Connected to device";
controller->discoverServices();
});
connect(controller, &QLowEnergyController::disconnected, this, [this]() {
qDebug() << "Disconnected";
});
controller->connectToDevice();
}
// Controller slots
void Bletest::serviceDiscovered(const QBluetoothUuid &gatt)
{
qDebug() << "Service discovered: " << gatt.toString();
if (gatt.toString().contains("0000181d-0000-1000-8000-00805f9b34fb")) {
service = controller->createServiceObject(QBluetoothUuid(QBluetoothUuid::WeightScale));
if (service) {
qDebug() << "Found weight scale service";
connect(service, &QLowEnergyService::stateChanged, this, &Bletest::serviceStateChanged);
connect(service, &QLowEnergyService::characteristicChanged, this, &Bletest::updateWeight);
connect(service, &QLowEnergyService::characteristicRead, this, &Bletest::updateWeight);
service->discoverDetails();
}
}
}
void Bletest::serviceScanFinished()
{
qDebug() << "Service scan finished";
}
////////////////////////////
// Service slots
void Bletest::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
if (controller->state() == QLowEnergyController::UnconnectedState)
return;
if (newState == QLowEnergyService::DiscoveringServices) {
qDebug() << "Discovering services state";
} else if (QLowEnergyService::ServiceDiscovered) {
qDebug() << "Service discovered.";
const QLowEnergyCharacteristic weightChar = service->characteristic(QBluetoothUuid(QBluetoothUuid::WeightMeasurement));
if (!weightChar.isValid()) {
qDebug() << "Weight data not found";
return;
}
qDebug() << "Weight data found";
//service->readCharacteristic(weightChar);
desc = weightChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if (desc.isValid()) {
qDebug() << "Writing descriptor";
service->writeDescriptor(desc, QByteArray::fromHex("0100"));
}
}
}
void Bletest::updateWeight(const QLowEnergyCharacteristic &c, const QByteArray &value)
{
qDebug() << "Updating weight";
if (c.uuid() != QBluetoothUuid(QBluetoothUuid::WeightMeasurement))
return;
double weight = qFromLittleEndian<qint16>(value.mid(1, 2).data()) * RESOLUTION;
qDebug() << "New weight: " << value.mid(1, 2);
qDebug() << "New weight: " + QString::number(weight, 'f', 2);
}
///////////////////////////
Can someone point me in the right direction with this? Is is even possible with BLE to automatically connects to my app and receive data?
Thanks.
I have a real bought comodo positive ssl certificate installed on apache and checked the correct installation through the site https://www.sslshopper.com/ssl-checker.html
in the kit with the certificate is 5 files
AddTrust_External_CA_Root.crt
COMODO_RSA_Certification_Authority.crt
sslserver.crt
sslserver.key
sslserver.ca-bundle
When I try to connect to my server via the chrome in the console, the following error occurs:
WebSocket connection to 'wss://192.165.10.70:5870/' failed: Error in
connection establishment: net::ERR_CERT_COMMON_NAME_INVALID
And on the server side:
Now listening on 0.0.0.0:5870 ("COMODO CA Limited") ("COMODO RSA
Domain Validation Secure Server CA") ("GB") New connection
peerCertificate QSslCertificate("", "", "1B2C1Y8AsgApgBmY7PhCtg==",
(), (), QMap(), QDateTime(Invalid), QDateTime(Invalid))
peerName ""
encrypted data
encrypted
ERROR "The remote host closed the connection"
ERROR: could not receive message (The remote host closed the
connection)
js client:
<script type="text/javascript">
let socket = new WebSocket("wss://192.165.10.70:5870");
socket.onmessage = function(response) {
console.log(response.data);
}
socket.onopen = function() {
socket.send("hi");
}
socket.onclose = function(e) {
if(e.wasClean) {
console.log('Close server connect');
}
else {
console.log('connect fail');
}
console.log('error: ' + e.code + ' reason: ' + e.reason);
}
socket.onerror = function(err) {
console.log('error: '+err.message);
}
</script>
Qt:
void ServerExample::run()
{
QHostAddress address = QHostAddress::Any;
quint16 port = 5870;
SslServer sslServer;
sslServer.setSslLocalCertificate("C:\\Users\\Adm\\Documents\\Server\\sslserver.pem");
sslServer.setSslPrivateKey("C:\\Users\\Adm\\Documents\\Server\\sslserver.key");
sslServer.setSslProtocol(QSsl::TlsV1_2);
if (sslServer.listen(address, port))
qDebug().nospace() << "Now listening on " << qPrintable(address.toString()) << ":" << port;
else
qDebug().nospace() << "ERROR: could not bind to " << qPrintable(address.toString()) << ":" << port;
if (sslServer.waitForNewConnection(-1)) // Wait until a new connection is received, -1 means no timeout
{
qDebug() << "New connection";
QSslSocket *sslSocket = dynamic_cast<QSslSocket*>(sslServer.nextPendingConnection());
qDebug() << "peerCertificate " << sslSocket->peerCertificate();
qDebug() << "peerName " << sslSocket->peerName();
QObject::connect(sslSocket, &QSslSocket::encrypted, [](){
qDebug() << "encrypted";
});
if (sslSocket->waitForReadyRead(-1))
{
QByteArray message = sslSocket->readAll();
qDebug() << "Message:" << QString(message);
sslSocket->disconnectFromHost();
sslSocket->waitForDisconnected();
qDebug() << "Disconnected";
}
else
{
qDebug().nospace() << "ERROR: could not receive message (" << qPrintable(sslSocket->errorString()) << ")";
}
}
else
{
qDebug().nospace() << "ERROR: could not establish encrypted connection (" << qPrintable(sslServer.errorString()) << ")";
}
this->deleteLater();
QThread::currentThread()->quit();
qApp->exit();
}
void SslServer::incomingConnection(qintptr socketDescriptor)
{
QSslSocket *sslSocket = new QSslSocket(this);
sslSocket->setSocketDescriptor(socketDescriptor);
qDebug() << m_sslLocalCertificate.issuerInfo(QSslCertificate::Organization);
qDebug() << m_sslLocalCertificate.issuerInfo(QSslCertificate::CommonName);
qDebug() << m_sslLocalCertificate.issuerInfo(QSslCertificate::CountryName);
sslSocket->setLocalCertificate(m_sslLocalCertificate);
sslSocket->setPrivateKey(m_sslPrivateKey);
sslSocket->setProtocol(m_sslProtocol);
sslSocket->setPeerVerifyMode(QSslSocket::VerifyNone);
sslSocket->startServerEncryption();
QObject::connect(sslSocket, &QSslSocket::encrypted, [=](){
qDebug() << "encrypted data";
});
QObject::connect(sslSocket, static_cast<void (QSslSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [sslSocket] (QAbstractSocket::SocketError) {
qDebug()<< "ERROR " << sslSocket->errorString();
});
QObject::connect(sslSocket, &QSslSocket::peerVerifyError, [sslSocket](QSslError err){
qDebug()<< "ERROR " << err.errorString();
});
QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(sslErrorst(const QList<QSslError> &)));
connect(sslSocket, &QSslSocket::hostFound, [](){
qDebug() << "host";
});
this->addPendingConnection(sslSocket);
}
I read similar articles, not one does not have a solution, how to correctly use the comodo certificate?
I'm using method QUdpSocket::writeDatagram and sending a lot of data. When the socket is full, the method return -1. Is it possible to do somethind like select() with a QUdpSocket?
while(!counterList.empty())
{
CounterValuePtr value = counterList.dequeue();
if (mUdpSocket->bytesToWrite() <= 1<<13)
{
const QByteArray datagram = toDatagram(*value);
qint64 sentBytes = 0;
try
{
sentBytes = mUdpSocket->writeDatagram(datagram, QHostAddress(mSettings->getConnectionIp()), mSettings->getConnectionPort());
}
catch(...)
{
emit dataLost();
qWarning() << "Exception";
throw;
}
qDebug() << datagram;
if(sentBytes == -1)
{
QString errorMsg = getErrorMsg(WSAGetLastError());
qWarning() << "SocketError (" << mUdpSocket->error() << ") : " << mUdpSocket->errorString() << ". " << errorMsg;
emit dataLost();
}
else if(sentBytes < datagram.size())
{
qWarning() << "Not all data sent";
emit dataLost();
}
else
{
qDebug() << "Counter "<< value->getName() << " sent";
datasent = true;
emit dataSent();
}
}
else
{
qWarning() << "Socket write buffer full. Dropping data.";
emit dataLost();
}
}
Some times, writeDatagram returns -1. When I print the last error with WSAGetLastError it prints the buffer is full.
I am trying to develop a Qt program using sockets for client and server communication. I need help with figuring out why my server crashes when the client connects and the server tries to get a QString?
I have this code on the server side:
void Client::onReadyRead() {
qDebug() << "On ready read!";
QDataStream in(mSocket);
in.setVersion(QDataStream::Qt_4_0);
for (;;) {
if(!mBlockSize) {
if (mSocket->bytesAvailable() < sizeof(quint16)) break;
in >> mBlockSize;
}
if(mSocket->bytesAvailable() < mBlockSize) break;
qDebug() << "Package was recieved!";
qDebug() << "Block size: " << mBlockSize;
if(Table::INVALID_ID == mUser.id()) {
QString authStr;
in >> authStr;
qDebug() << "Recieved account data: " << authStr;
}
mBlockSize = 0;
}
}
And on the client side:
void Client::onConnected()
{
qDebug() << "Connected!";
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
//Reserve 2 bytes
out << (quint16)0 << mEmail << "|" << mPassword;
//Back to the beginning
out.device()->seek(0);
//Write a block size
out << (quint16)(block.size() - sizeof(quint16));
mSocket->write(block);
}