Create a RFCOMM Server using Qt for symbian - qt

I´m new on Qt, Symbian devices and Bluetooth.
I have to set up a RFCOMM server to receive connection from a bluetooth device (its a pinpad) that only support SPP profile.
I searched on google and found some examples, like this: http://doc.qt.nokia.com/qtmobility/btchat.html
Tried everything but I can´t connect them. Both devices was paired, but when I try to connect it fails.
When I asked to the manufacturer, they said that it was happening because the SPP Server on my celphone was not avaiable to listen for incoming connections.
I´m creating the RFCOMM server and registering the service just like the example, but it still not working.
Someone can help me?
I'm using Qt with QtMobility 1.2.0 and my cellphone is a Nokia 500 (Symbian^3).
Here is my code:
void bluetooth::startServer()
{
QString deviceName;
QBluetoothLocalDevice localDevice;
if (rfcommServer)
return;
localDevice.powerOn();
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
deviceName = localDevice.name();
rfcommServer = new QRfcommServer(this);
connect(rfcommServer, SIGNAL(newConnection()), this, SLOT(vConectou())) ;
if( rfcommServer->listen(localDevice.address(),
quint16(rfcommServer->serverPort()) ) )
emit vExibeMsg("Listening");
else
emit vExibeMsg("Error");
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle,
(uint)0x00010010);
QBluetoothServiceInfo::Sequence classId;
classId << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceName, tr("Test Server"));
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceDescription,
tr("Test Bluetooth"));
serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceProvider, deviceName );
serviceInfo.setServiceUuid(QBluetoothUuid(QBluetoothUuid::Rfcomm));
serviceInfo.setAttribute(QBluetoothServiceInfo::BrowseGroupList,
QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
QBluetoothServiceInfo::Sequence protocolDescriptorList;
QBluetoothServiceInfo::Sequence protocol;
/*
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap));
protocolDescriptorList.append(QVariant::fromValue(protocol));
protocol.clear();
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
<< QVariant::fromValue(quint8(rfcommServer->serverPort()));
protocolDescriptorList.append(QVariant::fromValue(protocol));
protocol.clear();
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::SerialPort));
protocolDescriptorList.append(QVariant::fromValue(protocol));
*/
protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm))
<< QVariant::fromValue(quint8(rfcommServer->serverPort()));
protocolDescriptorList.append(QVariant::fromValue(protocol));
serviceInfo.setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList,
protocolDescriptorList);
if( serviceInfo.registerService() )
{
emit vExibeMsg("Waiting for connections...");
}
else
{
emit vExibeMsg("Error to create the service");
}
}

Related

Dubs Connman wifi connect Qt

I'am working on an imx6, and i'am trying to connect to a wifi network through Dbus with a Qt application.
The application connect correctly to connman via Dbus and i recieve correctly the wifi services.
The problem is that when i try to connect to a wiif network i catch this error :
"Method "Connect" with signature "ss" on interface "net.connman.Service" doesn't exist
The code that i'am using in Qt application to coonect to a wifi network is:
QDBusInterface *iface =
new QDBusInterface("net.connman","/net/connman/technology/wifi","net.connman.Service",QDBusConnection::systemBus());
if (!iface->isValid())
{
qDebug() << Q_FUNC_INFO << "Fail to connect to the Connman Technology interface: " << QDBusConnection::systemBus().lastError().message();
}
QDBusReply<void> reply = iface->call("Connect","/net/connman/service/wifi_88da1a4db14c_41684179_managed_psk","password");
if (!reply.isValid())
{
qDebug() << "Call connect result: " << reply.error().message();
}
When i try to connect to the wifi network with shell commands using connmanctl it works like a charm.
I had the same problem on imx6. The solution which works for me is creating a configuration file for network before invoking Connect method.
The file should be in /var/lib/connman and name [SSID].config .
File content:
[service_wifi_PUT_SERVICE_NAME]
Name = PUT_SSID
Type = wifi
Passphrase = PUT_PASSWORD
And try connecting in this way:
QDBusInterface *iface = new QDBusInterface("net.connman", QString{"/net/connman/service/%1"}.arg(SERVICE_NAME), "net.connman.Service", QDBusConnection::systemBus());
QDBusReply<void> reply = iface->call("Connect");
if(!reply.isValid() {
...

How to open a QNetworkSession to a WiFi AP specifying which physical interface to use?

My computer has 2 wlan interfaces: One integrated ("Wi-Fi") and an external adapter ("Wi-Fi 2"). How can I make my Qt application establish a connection to a given access point (AP) through the second interface?
I want to make sure that the first interface is always used to connect to the internet (my ISP router), while the second interface is used to connect to a third-party device (which is a Wi-Fi AP itself).
The following code connects to an AP (SSID = DeviceRouter). But I don't know how to force using my secondary interface (Wi-Fi 2).
// My target SSID and interface (let's assume this is an open AP)
QString ssid = "DeviceRouter";
QString interface = "Wi-Fi 2"; // I want to use my secondary interface
// Get all configurations
QNetworkConfigurationManager mgr;
mgr.updateConfigurations();
waitForSignal( &mgr, SIGNAL( updateCompleted() ), 20000 ); // implemented elsewhere
QList<QNetworkConfiguration> allConfigs = mgr.allConfigurations();
// Select the configuration matching my target SSID
bool connected = false;
foreach( QNetworkConfiguration config, allConfigs ) {
if( config.name() == ssid && config.bearerType == QNetworkConfiguration::BearerWLAN ) {
QNetworkSession s( config );
// How can I set the interface for the session?
s.open();
connected = w.waitForOpened( 30000 );
if( connected ) {
qDebug() << "You're connected on interface: " << s.interface().humanReadableName();
}
break;
}
}
So, output is always You're connected on interface: Wi-Fi 2.

Qt How to properly connect to a phone programmatically (Bluetooth A2DP, AVRCP, HSP, HFP) in Linux

I am trying to develop an application that uses bluez stack along with pulseaudio and ofono in order to connect to a phone and achieve tasks such as media playback (A2DP), media control (AVRCP), and handsfree-based telephony (HFP). When I connect to my phone through bluetoothctl, it automatically connects to all the available profiles, so using all profiles A2DP, AVRCP, HFP through my program is achievable. If I don't connect to my phone using bluetoothctl, handsfree /HFP modem is not enabled/powered in ofono.
However, when I use QBluetoothSocket in Qt and connect using a profile, there is always a profile that is not connected. For example connecting to Handsfree profile, telephony works, but the media control does not work. In short, I want to be able to connect to bluetooth as bluetoothctl does. What I have in Qt is as follows (in short):
static const QList<QBluetoothUuid> audioUuids = QList<QBluetoothUuid>()
<< QBluetoothUuid::HeadsetAG
<< QBluetoothUuid::AV_RemoteControlTarget;
..
void BtConnection::setConnection(int index)
{
if(m_bluetoothSocket == nullptr) {
m_bluetoothSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
qDebug() << "Created Bluetooth Socket";
}
if(m_bluetoothSocket != nullptr) {
connect(m_bluetoothSocket, SIGNAL(connected()), this, SLOT(connected()));
connect(m_bluetoothSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(m_bluetoothSocket, SIGNAL(error(QBluetoothSocket::SocketError)),
this, SLOT(connectionError(QBluetoothSocket::SocketError)));
}
m_device = get(index);
// Check if an element in m_device.serviceUuids() match with an element in audioUuids
QList<QBluetoothUuid>::const_iterator uuid;
for (uuid = audioUuids.begin(); uuid != audioUuids.end(); ++uuid) {
if(m_device.serviceUuids().indexOf(*uuid) > 0) {
// This device supports one of the uuids we have scanned for
if(m_bluetoothSocket != nullptr) {
qDebug() << "*****Connecting... " << *uuid;
m_bluetoothSocket->connectToService(m_device.address(), *uuid);
return;
}
}
}
qDebug() << "*****Cannot connect to service...";
}
I would be willing to post more of the code if this is not clear to you. Any help is greately appreciated on how to connect to bluetooth with Qt as bluetoothctl does.
Not a direct answer but you might want to check KDE's KDEConnect project. It already does what you are looking for and might either be a source of inspiration or you could contribute to the project.

How to get name of WiFi using QT quick application on Android

I am trying to develop a code to get name of wifi connected to my android phone. My code sample is
QStringList WiFisList;
QNetworkConfiguration cfg;
QNetworkConfigurationManager ncm;
auto nc = ncm.allConfigurations();
for (auto &x : nc)
{
qDebug()<< "CHECK1 " << x.bearerType();
if (x.bearerType() == QNetworkConfiguration::BearerWLAN)
{ qDebug ()<<"CHECK2";
qDebug() <<"WIFI is"<<x.name();
}
}
Output of this code is just returning me:
(int main(int, char)): WIFI is "WiFi" but my expected output is ASUS_XOOTD
How can I get this as output? Is something missing in my code?
check that your qt version is supporting Bearer extension for android.

Winsock bind() failing with WSAEADDRNOTAVAIL for directed broadcast address

I am setting up a UDP socket and trying to bind what should be a valid network broadcast address to it (192.168.202.255 : 23456), but bind fails with error 10049, WSAEADDRNOTAVAIL. If I use a localhost broadcast address, 127.0.0.255, it succeeds.
WSAEADDRNOTAVAIL's documentation says that "The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0)." But I think this address, 192.168.202.255, should be a valid broadcast address because of the following entry when running ipconfig:
What might be the problem?
Code
I am new to Winsock programming and am probably making an elementary error, but I can't find it. The code I have so far is:
m_ulAddress = ParseIPAddress(strAddress);
// Winsock 2.2 is supported in XP
const WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA oWSAData;
const int iError = WSAStartup(wVersionRequested, &oWSAData);
if (iError != 0) {
PrintLine(L"Error starting the network connection: WSAStartup error " + IntToStr(iError));
} else if (LOBYTE(oWSAData.wVersion) != 2 || HIBYTE(oWSAData.wVersion) != 2) {
PrintLine(L"Error finding version 2.2 of Winsock; got version " + IntToStr(LOBYTE(oWSAData.wVersion)) + L"." + IntToStr(HIBYTE(oWSAData.wVersion)));
} else {
m_oSocket = socket(AF_INET, SOCK_DGRAM /*UDP*/, IPPROTO_UDP);
if (m_oSocket == INVALID_SOCKET) {
PrintLine(L"Error creating the network socket");
} else {
// Socket needs to be able to send broadcast messages
int iBroadcast = true; // docs say int sized, but boolean values
if (setsockopt(m_oSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&iBroadcast, sizeof(iBroadcast)) != 0) {
PrintLine(L"Error setting socket to allow broadcast addresses; error " + IntToStr(WSAGetLastError()));
} else {
m_oServer.sin_family = AF_INET;
m_oServer.sin_port = m_iPort;
m_oServer.sin_addr.S_un.S_addr = m_ulAddress;
// !!! This is the failing call
if (bind(m_oSocket, (sockaddr*)&m_oServer, sizeof(m_oServer)) == -1) {
PrintLine(L"Error binding address " + String(strAddress.c_str()) + L":" + IntToStr(m_iPort) + L" to socket; error " + IntToStr(WSAGetLastError()));
} else {
m_bInitialisedOk = true;
}
}
}
}
Comments
ParseIPAddress is a wrapper around inet_addr; inspecting the value of m_oServer.sin_addr.S_un.S_addr it appears to be correct. m_oSocket is a SOCKET. I added the call to setsockopt since you can't broadcast via anything but TCP by default (see the second paragraph in sendto's Remarks); this call doesn't make any difference. PrintLine is a wrapper to the console output. The odd String / c_str() casts are converting to and from C++ wstrings to VCL Unicode strings, since I am using C++ Builder and its VCL libraries. The IP address is a narrow (char) string.
The sendto documentation states that "If a socket is opened, a setsockopt call is made, and then a sendto call is made, Windows Sockets performs an implicit bind function call." This implies that bind is not needed at all. If I omit the call, then calling sendto like so:
const int iLengthBytes = strMessage.length() * sizeof(char); // Narrow string
const int iSentBytes = sendto(m_oSocket, strMessage.c_str(), iLengthBytes, 0, (sockaddr*)&m_oServer, sizeof(m_oServer));
if (iSentBytes != iLengthBytes) {
PrintLine(L"Error sending network message; error: " + IntToStr(WSAGetLastError()));
fails with error 10047, WSAEAFNOSUPPORT, "Address family not supported by protocol family."
The output of netsh winsock show catalog (mentioned at the bottom of socket's Remarks) is lengthy but does include several entries mentioning UDP and IPv4.
A possible complication is that this is running in a VMWare Fusion host; Fusion does have an odd setup for networks. I also have a Cisco VPN configured running back to my office. Connecting and disconnecting this makes no difference.
One thing that seems dodgy to me is hard-casting the SOCKET m_oSocket to sockaddr, but this seems to be normal practice for Winsock programming when I've been reading examples. Reading up it may be required since the underlying interpretation depends on the protocol family. It seems a potential source of error, but I'm not sure how to avoid it.
Any ideas? I am stumped :)
Setup
Windows 7 Pro running on VMWare Fusion 4.1.3
The program is compiled as 32-bit with Embarcadero C++ Builder 2010.
The program is a console program only
Much confusion here. I'll address it point by point for your edification, but if you just want working code, skip to the end.
// Winsock 2.2 is supported in XP
Actually, Winsock 2.2 goes back to NT 4 SP4, which dates it to 1998. Because of that, I wouldn't bother checking oWSAData.wVersion in the error case. There's basically no chance this is going to happen any more.
If broad portability is your goal, I'd target Winsock 1.1, which is all you need for the code you show, and will let the code build and run on anything that supports Winsock, even back to Windows 3.x.
m_oSocket = socket(AF_INET, SOCK_DGRAM /*UDP*/, IPPROTO_UDP);
Bad style. You should use PF_INET here instead of AF_INET. They have the same value, but you're not specifying an address family (AF) here, you're specifying a protocol family (PF). Also, the third parameter can safely be zero, because it's implied by the first two parameters. Again, it's just a style fix, not a functional fix.
int iBroadcast = true; // docs say int sized, but boolean values
Yup. Don't second-guess the docs and use bool here. Remember, Winsock is based on BSD sockets, and that goes back to the days before C++ existed.
m_oServer.sin_addr.S_un.S_addr = m_ulAddress;
You really shouldn't be digging into the internals of the sockaddr_in structure this way. The sockets API has a shortcut for that, which is shorter and hides some of the internal implementation details. It is:
m_oServer.sin_addr.s_addr = m_ulAddress;
Moving on...
if (bind(m_oSocket, ...
Although Remy is right that the bind() call isn't correct, you actually don't need it at all. You can depend on your system's routing layer to send the packet out the right interface. You don't need to "help" it with a bind() call.
you can't broadcast via anything but TCP by default (see the second paragraph in sendto's Remarks);
You've misunderstood what MSDN is telling you. When you see the term "TCP/IP", it often (but not always!) includes UDP. They're using it in that generic sense here.
The MSDN bit you point to talks about TCP/IP because Winsock was created in a world when TCP/IP had not yet won the network protocol wars. They're trying to restrict the discussion to TCP/IP (UDP, really) so you don't get the idea that what they're saying applies to other network transports supported by Winsock stacks in the early days: NetBIOS, IPX, DECNet...
In fact, you can only broadcast (or multicast) using UDP sockets. TCP is point-to-point, only.
One thing that seems dodgy to me is hard-casting the SOCKET m_oSocket to sockaddr,
That's also part of the multiple network transport support in sockets. In addition to sockaddr_in, there's sockaddr_ipx for IPX, sockaddr_dn for DECnet... Winsock is a C API, not a C++ API, so we can't subclass sockaddr and pass a reference to the base class, or create function overloads for each of the variations. This trick of casting structures is a typical C way to get a kind of polymorphism.
Here's a working example, which builds with MinGW, g++ foo.cpp -o foo.exe -lwsock32:
#include <winsock.h>
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, char* argv[])
{
WSADATA wsa;
if (WSAStartup(MAKEWORD(1, 1), &wsa)) {
cerr << "Failed to init Winsock!" << endl;
return 1;
}
// Get datagram socket to send message on
SOCKET sd = socket(PF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
cerr << "socket() failed: " << WSAGetLastError() << endl;
return 1;
}
// Enable broadcasts on the socket
int bAllow = 1;
if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char*)&bAllow,
sizeof(bAllow)) < 0) {
cerr << "setsockopt() failed: " << WSAGetLastError() << endl;
closesocket(sd);
return 1;
}
// Broadcast the request
string msg = "Hello, world!";
const int kMsgLen = msg.length();
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
const uint16_t kPort = 54321;
sin.sin_port = htons(kPort);
sin.sin_family = AF_INET;
if (argc == 1) {
sin.sin_addr.s_addr = INADDR_BROADCAST;
}
else if ((sin.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) {
cerr << "Couldn't parse IP '" << argv[1] << "'!" << endl;
}
int nBytes = sendto(sd, msg.c_str(), kMsgLen, 0,
(sockaddr*)&sin, sizeof(struct sockaddr_in));
closesocket(sd);
// How well did that work out, then?
if (nBytes < 0) {
cerr << "sendto() IP " << inet_ntoa(sin.sin_addr) <<
" failed" << WSAGetLastError() << endl;
return 1;
}
else if (nBytes < kMsgLen) {
cerr << "WARNING: Short send, " << nBytes << " bytes! "
"(Expected " << kMsgLen << ')' << endl;
return 1;
}
else {
cerr << "Sent " << kMsgLen << "-byte msg to " <<
inet_ntoa(sin.sin_addr) << ':' << kPort << '.' << endl;
}
return 0;
}
It sends to 255.255.255.255 (INADDR_BROADCAST) by default, but if you pass a directed broadcast IP (such as your 192.168.202.255 value) as the first parameter, it will use that instead.
You should not bind() to a broadcast IP address. You need to bind() to an individual network adapter IP instead. If you want to send out a broadcast message, you bind() to the adapter that is going to send the broadcast, and then sendto() the broadcast IP. If you want to receive a broadcast message, you bind() to the specific adapter whose IP matches the broadcast IP being sent to.

Resources