How to get QDBusConnection::connect() failure reason - qt

I'm trying to connect to a D-Bus signal this way:
bool result = QDBusConnection::systemBus().connect(
"foo.bar", // service
"/foo/bar", // path
"foo.bar", // interface
"SignalSomething",
this,
SLOT(SignalSomethingSlot()));
if( !result )
{
// Why!?
}
QDBusConnection::connect() returns a boolean, how do I get extended error information? If a check QDBusConnection::lastError() it returns no useful information (as QDBusError::isValid() is false).

I had the same issue and it turned out that the slot I connected to had the wrong parameter types. They must match according to Qt's documentation and it looks like connect() verifies that, despite not explicitly mentioned.
Warning: The signal will only be delivered to the slot if the parameters match.
I suggest d-feet to list signals and check their parameter types. dbus-monitor does list signals, paths and such too, but not always the exact type of parameters.
One important observation though: I fixed the issue in my particular case by using different slot parameters than the actual signal has!
I wanted to connect to a com.ubuntu.Upstart0_6 signal mentioned here to detect when the screen in Ubuntu is locked/unlocked. dbusmonitor prints the following and d-feet shows parameters (String, Array of [String])
// dbusmonitor output
signal time=1529077633.579984 sender=:1.0 -> destination=(null destination) serial=809 path=/com/ubuntu/Upstart; interface=com.ubuntu.Upstart0_6; member=EventEmitted
string "desktop-unlock"
array [
]
Hence the signal should be of type
void screenLockChangedUbuntu(QString event, QVector<QString> args) // connect() -> false
This however made connect() return false. The solution was to remove the array parameter from the slot:
void screenLockChangedUbuntu(QString event) // works
I am aware that the array parameter was always empty, but I cannot explain why it only worked when removing it.

You could try these tricks:
1) Set QDBUS_DEBUG environment variable before running your application.
export QDBUS_DEBUG=1
2) Start dbus-monitor to see what's happening on the bus. You may need to set a global policy to be able to eavesdrop system bus depending on your distro.
Update:
Are you sure connecting to the system bus succeeded? If it fails you should probably check system.conf policy and possibly create own conf in system.d. This post might be helpful.
You could first connect to the system bus with QDBusConnection::connectToBus and check if it succeeded with QDBusConnection::isConnected. Only after that you try to connect to the signal and check if that succeeded.
QDBusConnection bus = QDBusConnection::connectToBus(QDBusConnection::systemBus, myConnectionName);
if (bus.isConnected())
{
if(!bus.connect( ... ))
{
// Connecting to signal failed
}
}
else
{
// Connecting to system bus failed
}

Related

how to block the command "clEnqueueFillImage",which don't have the blocking argument?

In the source code of funciton "clEnqueueFillImage",it want to blocking the command but I don't figure out how to blocking it without the blocking argument?
{
iResult = OCL_Flush(psCommandQueue);
if (iResult != CL_SUCCESS)
{
PVR_DPF((PVR_DBG_ERROR, "Failed implicit flush before blocking write."));
goto exit;
}
}```
clEnqueueFillImage, like many other functions in OpenCL, has and event out parameter. From the documentation:
Returns an event object that identifies this particular write
command and can be used to query or queue a wait for this particular
command to complete. event can be NULL in which case it will not be
possible for the application to query the status of this command or
queue a wait for this command to complete.
So you could simply use the returned event:
cl_event sync_event{};
CL_CHECK_ERROR(clEnqueueFillImage(... , &sync_event);
CL_CHECK_ERROR(clWaitForEvents(1, &sync_event));

writing to GATT descriptor produces write not permitted error

I'm using java TinyB to connect to a TimeFlip device with Bluetooth LE.
When trying to write to the Descriptor of the Facet Characteristic to recieve notifications I always get the error:
Exception in thread "main" tinyb.BluetoothException: GDBus.Error:org.bluez.Error.NotPermitted: Write not permitted
But when I write to the same Descriptor using gatttool it works and i get the notifications.
BluetoothGattService timeFlipService = device.find("f1196f50-71a4-11e6-bdf4-0800200c9a66", Duration.ofSeconds(5));
BluetoothGattCharacteristic facets = timeFlipService.find("f1196f52-71a4-11e6-bdf4-0800200c9a66", Duration.ofSeconds(5));
BluetoothGattDescriptor facetsConfig = facets.find("00002902-0000-1000-8000-00805f9b34fb", Duration.ofSeconds(5)); // like this ==> always null, custom method works???
if(!login(timeFlipService)) {log.error("login to TimeFlip failed");}
try{
byte[] enableNotifications = {0x01, 0x00};
facetsConfig.writeValue(enableNotifications); //when facesConfig assigned with custom method throws write not permitted error
facets.enableValueNotifications(new FacetNotification());
}
catch(NullPointerException e){
log.error("NullPointerException in " + (facets == null ? "facet characteristic" : "facet descriptor"));
}
catch(BluetoothException b){
log.error(b.getMessage());
}
}
The mentioned "custom method" just gets all Descriptor from a characteristic and returns the one matching a given uuid, as the find() method times out every time.
In Bluez you are supposed to use StartNotify to turn on notifications or indications. Bluez will do the writing of the descriptor for you but if you try to do it yourself it indeed gives an error.

Qt Signal and slots not working as expected

When the socket times out while waiting for a read it occasionally fails. But when it does fail, it continuously fails, and the log message in slotDisconnected never gets reported despite mpSocket's disconnected signal being connected to slotDisconnect(). It's as if the return statement in slotConnected isn't being hit and it's going round in a continous loop.
void Worker::slotDisconnected()
{
// Attempt to reconnect
log("Disconnected from Server. Attempting to reconnect...");
// fires mpSocket's connect signal (which is connected to slotConnected)
connectToServer();
}
void Worker::slotConnected()
{
// Loop forever while connected and receiving messages correctly
while(1)
{
if(mpSocket->bytesAvailable())
{
// A message is ready to read
}
else if(!mpSocket->waitForReadyRead(mSocketTimeOut))
{
// waitForReadyRead returned false - instead of continuing and trying again, we must disconnect as sometimes
// (for some unknown reason) it gets stuck in an infinite loop without disconnecting itself as it should
log("Socket timed out while waiting for next message.\nError String: " + mpSocket->errorString());
msleep(3000);
mpSocket->disconnect();
return;
}
}
}
The signals/slots are connected like so:
connect(mpSocket, &QAbstractSocket::disconnected, this, &TRNGrabberWorker::slotDisconnected);
connect(mpSocket, &QAbstractSocket::connected, this, &TRNGrabberWorker::slotConnected);
Anyone have any idea's what's going on? Would be much appreciated
To disconnect from server use mpSocket->disconnectFromHost(); instead of mpSocket->disconnect();.
Actually mpSocket->disconnect(); disconnects all signals/slots of object mpSocket.

Qt TCP/IP socket connection check

I am writing Qt TCP/IP client. I want to check the connection state with server before send data to sever.
As far my knowledge I can do this by following methods
Use a bool 'ConnectionState', set this variable when connected with
sever and reset this variable on disconnected() signal. Now before
sending data to server (client->write()) check the value of this
variable.
use this 'client->state() == QTcpSocket::ConnectedState' way to check the connection state.
Which is good practice. Or any other method to this.
Thanks In advance.
QTCPSocket is derived from QAbstractSocket, which provides a state() function. This returns one of the following enums: -
enum SocketState { UnconnectedState, HostLookupState, ConnectingState, ConnectedState, ..., ListeningState }
So, assuming m_pSocket is a QTcpSocket, you would simply do this to check if it is connected:-
bool connected = (m_pSocket->state() == QTcpSocket::ConnectedState);
You could add a boolean and keep track of the state, but if a network error occurs you need to ensure that it is always in-sync with the actual connection state.
You can use errorOccurred signal and It's just enough for this signal define a slot in client. when an error occurs, a signal trigger and you can receive notify in slot function.
In client.h
/* define a slot for client */
public slots:
void errorOccurred(QAbstractSocket::SocketError error);
In client.c
/*client constructor*/
Client::Client(QObject *parent) {
/*some other code here*/
connect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
this, SLOT(errorOccurred(QAbstractSocket::SocketError)));
/*and maybe some other code here*/
}
and in client.c write implementation for errorOccurred:
void Client::errorOccurred(QAbstractSocket::SocketError error) {
qDebug() << "error in connection: " << socket->errorString();
}
OUTPUT:
error in connection: "Connection refused"

Photon Networking Instantiate Error (Unity3d)

Ok, so I'm making an online FPS in Unity and I was scripting that Photon Networking Script to connect and spawn the player and I keep getting these two errors:
Assets/Resources/GameManager.cs(64,23): error CS1502: The best overloaded method match for `PhotonNetwork.Instantiate(string, UnityEngine.Vector3, UnityEngine.Quaternion, int)' has some invalid arguments
Assets/Resources/GameManager.cs(64,23): error CS1503: Argument `#1' cannot convert `UnityEngine.Transform' expression to type `string'
Here is where the error is in my code:
// When Connected [Photon Callback]
void OnJoinedRoom()
{
PhotonNetwork.Instantiate(playerPrefab, transform.position, Quaternion.identity, 0);
}
//In Game: Disconnect from room.
void InGameGUI()
{
if (GUILayout.Button("Leave Game"))
PhotonNetwork.LeaveRoom();
}
}
And I did reference the Transform at the top:
public Transform playerPrefab;
Any ideas on what I did wrong and how I could fix it. Please help!
PhotonNetwork.Instantiate requires a string, not a Transform object as it's first parameter. (I do believe this was changed from a Transform object a while ago). Simply name the prefab that you want to instantiate (which must be in the Resources folder).

Resources