Git Product home page Git Product logo

dbus.dart's Introduction

Pub Package codecov

A native Dart client implementation of D-Bus.

Accessing remote objects

The easiest way to get started is to generate Dart classes from a D-Bus interface definition, for example:

<node name="/com/example/Test/Object">
  <interface name="com.example.Test">
    <property name="Version" type="s" access="read"/>
    <method name="ReverseText">
      <arg name="input" type="s" direction="in"/>
      <arg name="output" type="s" direction="out"/>
    </method>
  </interface>
</node>

The dart-dbus tool processes this interface to generate a Dart source file:

$ dart-dbus generate-remote-object test-object.xml -o test-remote-object.dart

You can then use the generated test-remote-object.dart to access that remote object from your program:

import 'package:dbus/dbus.dart';
import 'test-remote-object.dart';

Future<void> main() async {
  var client = DBusClient.session();
  var object = ComExampleTestObject(client, 'com.example.Test');
  var version = await object.getVersion();
  print('version: $version');
  var reversedText = await object.callReverseText('Hello World');
  print(reversedText);
  await client.close();
}

The code generated by dart-dbus may not be the cleanest API you want to expose for your service. It is recommended that you use the generated code as a starting point and then modify it as necessary.

Exporting local objects

The above interface definition can also be processed to generate a class for exporting this object.

$ dart-dbus generate-object test-object.xml -o test-object.dart

You can then use the generated test-object.dart in your program:

import 'package:dbus/dbus.dart';
import 'test-object.dart';

class TestObject extends ComExampleTestObject {
  @override
  Future<DBusMethodResponse> getVersion() async {
    return DBusGetPropertyResponse(DBusString('1.2'));
  }

  @override
  Future<DBusMethodResponse> doReverseText(String input) async {
    var reversedText = String.fromCharCodes(input.codeUnits.reversed);
    return DBusMethodSuccessResponse([DBusString(reversedText)]);
  }
}

Future<void> main() async {
  var client = DBusClient.session();
  await client.requestName('com.example.Test');
  await client.registerObject(TestObject());
}

Using objects without dbus-dart

You can also choose to access D-Bus objects directly without interface definitions and dbus-dart. This requires writing more code and handing more error cases.

The following code shows how to access the remote object in the above examples:

import 'package:dbus/dbus.dart';

Future<void> main() async {
  var client = DBusClient.session();
  var object = DBusRemoteObject(client, name: 'com.example.Test', path: DBusObjectPath('/com/example/Test/Object'));
  var value = await object.getProperty('com.example.Test', 'Version', signature: DBusSignature('s'));
  var version = value.asString();
  print('version: $version');
  var response = await object.callMethod('com.example.Test', 'ReverseText', [DBusString('Hello World')], replySignature: DBusSignature('s'));
  var reversedText = response.values[0].asString();
  print('$reversedText');
  await client.close();
}

And the following shows how to export that object:

import 'package:dbus/dbus.dart';

class TestObject extends DBusObject {
  TestObject() : super(DBusObjectPath('/com/example/Test/Object'));

  @override
  Future<DBusMethodResponse> getProperty(String interface, String name) async {
    if (interface == 'com.example.Test' && name == 'Version') {
      return DBusGetPropertyResponse(DBusString('1.2'));
    } else {
      return DBusMethodErrorResponse.unknownProperty();
    }
  }

  @override
  Future<DBusMethodResponse> handleMethodCall(DBusMethodCall methodCall) async {
    if (methodCall.interface == 'com.example.Test') {
      if (methodCall.name == 'ReverseText') {
        if (methodCall.signature != DBusSignature('s')) {
          return DBusMethodErrorResponse.invalidArgs();
        }
	var input = methodCall.values[0].asString();
        var reversedText = String.fromCharCodes(input.codeUnits.reversed);
        return DBusMethodSuccessResponse([DBusString(reversedText)]);
      } else {
        return DBusMethodErrorResponse.unknownMethod();
      }
    } else {
      return DBusMethodErrorResponse.unknownInterface();
    }
  }
}

Future<void> main() async {
  var client = DBusClient.session();
  await client.requestName('com.example.Test');
  await client.registerObject(TestObject());
}

Contributing to dbus.dart

We welcome contributions! See the contribution guide for more details.

dbus.dart's People

Contributors

adrianboyko avatar jpnurmi avatar kenvandine avatar lucyllewy avatar maikub avatar marcustomlinson avatar robert-ancell avatar taha-firoz avatar wazzaps avatar yash1200 avatar zanderso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dbus.dart's Issues

Add cached properties support to dart-dbus

The remote object classes that dart-dbus generates require the user to do a method call for each property. Optionally we should allow cached properties like we've used in upower.dart. This is similar to what gdbus-codegen does.

Find way to hide DBusObject.client

DBusObject.client is a variable and can be modified by an API user. It's required to emit signals, but should ideally be hidden or made final.

DBusClient doesn't cancel its internal subscription on close

Steps:

  • create DBusClient
  • create DBusRemoteObject
  • call & await DBusRemoteObject.getProperty()
  • close DBusClient

=> Often results to: Unhandled Exception: Bad state: StreamSink is closed due to an internal NameOwnerChanged signal subscription and an attempt to call Socket.add() after closing it.

Test-case:

import 'package:dbus/dbus.dart';

void main() async {
  final systemBus = DBusClient.system();

  final remoteObject = DBusRemoteObject(
    systemBus,
    'org.freedesktop.UPower',
    DBusObjectPath('/org/freedesktop/UPower/devices/DisplayDevice'),
  );
  await remoteObject.getProperty('org.freedesktop.UPower.Device', 'Percentage');

  systemBus.close();
}

Stacktrace:

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Bad state: StreamSink is closed
#0      _StreamSinkImpl.add  (dart:io/io_sink.dart:154:7))
#1      _Socket.add  (dart:io-patch/socket_patch.dart:1848:38))
#2      DBusClient._sendMessage                     package:dbus/src/dbus_client.dart:707
<asynchronous suspension>
#3      DBusClient._sendMethodCall                  package:dbus/src/dbus_client.dart:655
#4      DBusClient._callMethod                      package:dbus/src/dbus_client.dart:633
#5      DBusClient.callMethod                       package:dbus/src/dbus_client.dart:276
#6      DBusClient._addMatch                        package:dbus/src/dbus_client.dart:447
#7      _DBusSignalSubscription.onListen            package:dbus/src/dbus_client.dart:67
#8      _runGuarded  (dart:async/stream_controller.dart:847:24))
#9      _StreamController._subscribe.<anonymous closure>  (dart:async/stream_controller.dart:726:7))
#10     _BufferingStreamSubscription._guardCallback  (dart:async/stream_impl.dart:435:13))
#11     _StreamController._subscribe  (dart:async/stream_controller.dart:725:18))
#12     _ControllerStream._createSubscription  (dart:async/stream_controller.dart:860:19))
#13     _StreamImpl.listen  (dart:async/stream_impl.dart:493:9))
#14     _StreamIterator._initializeOrDone  (dart:async/stream_impl.dart:1041:30))
#15     _StreamIterator.moveNext  (dart:async/stream_impl.dart:1028:12))
#16     DBusClient.subscribeSignals (package:dbus/src/dbus_client.dart)
<asynchronous suspension>
#17     DBusClient._connect                         package:dbus/src/dbus_client.dart:395
<asynchronous suspension>
#18     DBusClient._sendMessage                     package:dbus/src/dbus_client.dart:703
#19     DBusClient._sendMethodCall                  package:dbus/src/dbus_client.dart:655
#20     DBusClient._callMethod                      package:dbus/src/dbus_client.dart:633
#21     DBusClient.callMethod                       package:dbus/src/dbus_client.dart:276
#22     DBusRemoteObject.getProperty                package:dbus/src/dbus_remote_object.dart:83
#23     main

Add API for name acquisition/loss

Add API for name acquisition/loss - handle the org.freedesktop.DBus.NameAcquired/NameLost signals and expose them to the user in some way.

Crash closing DBusClient while operation in progress

import 'package:dbus/dbus.dart';

void main() async {
  var client = DBusClient.system();
  var object = DBusRemoteObject(client, 'org.freedesktop.hostname1', DBusObjectPath('/org/freedesktop/hostname1'));
  await object.getProperty('org.freedesktop.hostname1', 'Hostname');
  await client.close();
}

causes:

Unhandled exception:
Bad state: StreamSink is closed

Needs some sort of checks to properly complete method calls when closed.

Changed behavior and workaround

Hi

Today I was writing some tests on my package that uses this package and I noticed some stuff has changed a little.

In the past, I used to call a method that received no parameters and returned nothing (precisely, org.freedesktop.Avahi.ServiceBrowser.Start()) which in the past didn't throw an exception when calling this method on Avahi versions lesser than 0.8.

I was wondering, that since that method was added to the Avahi D-Bus API with the express purpose of being backward-compatible with old versions of Avahi (Ubuntu 20.04 LTS currently ships version 0.7).Is there a way I can get the old nothing happens behavior explicitly?

Most of the interfacing code is autogenerated from Avahi xml file definitions, but I keep my own changes on those generated classes.

/// Invokes org.freedesktop.Avahi.ServiceBrowser.Start()
  Future<void> callStart() async {
    var result = await callMethod('org.freedesktop.Avahi.ServiceBrowser', 'Start', []);
    if (result.signature != DBusSignature('')) {
      throw 'org.freedesktop.Avahi.ServiceBrowser.Start returned invalid values \${result.values}';
    }
  }

This on my tests throws the following exception

Expected: null
  Actual: DBusMethodResponseException:<org.freedesktop.DBus.Error.UnknownMethod: Method "Start" with signature "" on interface "org.freedesktop.Avahi.ServiceBrowser" doesn't exist
          >
Expected no exceptions. Check if the service exists on the platform or the code broke

In case you wanted to replicate this issue, the code that triggers I suspect is
https://github.com/Piero512/bonsoir_linux_dbus/blob/main/lib/src/linux_dbus_bonsoir_discovery.dart#L61-L107

Disallow containers as keys in DBusDict

From the spec:
"A DICT_ENTRY works exactly like a struct, but rather than parentheses it uses curly braces, and it has more restrictions. The restrictions are: it occurs only as an array element type; it has exactly two single complete types inside the curly braces; the first single complete type (the "key") must be a basic type rather than a container type. Implementations must not accept dict entries outside of arrays, must not accept dict entries with zero, one, or more than two fields, and must not accept dict entries with non-basic-typed keys. A dict entry is always a key-value pair."

Suggestion: auto-generated header comment

It's a matter of taste, but I personally like the convention that generated Dart files usually contain a header comment stating that the file was generated, and that should not be edited. What they usually miss, though, is any info on how the file was generated, or where it originates from. It would be awesome to have something like:

// DO NOT EDIT. THIS FILE IS GENERATED.
// dart-dbus generate-remote-object org.freedesktop.FooBar.xml

Naming conflicts with NetworkManager's PropertiesChanged signals

NetworkManager has some annoying deprecated PropertiesChanged signals, which are causing naming conflicts with DBusRemoteObject.subscribePropertiesChanged().

  • org.freedesktop.NetworkManager.PropertiesChanged
  • org.freedesktop.NetworkManager.AccessPoint.PropertiesChanged
  • org.freedesktop.NetworkManager.Device.PropertiesChanged
  • ...

For example:

$ dart-dbus generate-remote-object org.freedesktop.NetworkManager.xml

=>

  /// Subscribes to org.freedesktop.NetworkManager.PropertiesChanged
  Future<DBusSignalSubscription> subscribePropertiesChanged(void Function(Map<String, DBusValue> properties) callback) async {
    return await subscribeSignal('org.freedesktop.NetworkManager', 'PropertiesChanged', (values) {
      if (values.length == 1 && values[0].signature == DBusSignature('a{sv}')) {
        callback((values[0] as DBusDict).children.map((key, value) => MapEntry((key as DBusString).value, (value as DBusVariant).value)));
      }
    });
  }

=>

'OrgFreedesktopNetworkManager.subscribePropertiesChanged' ('Future Function(void Function(Map<String, DBusValue>))') isn't a valid override of 'DBusRemoteObject.subscribePropertiesChanged' ('Future Function(void Function(String, Map<String, DBusValue>, List))').

Add D-Bus server class

Not a high priority but for symmetry we should consider a D-Bus server implementation. It would then probably make sense to rename the project to dbus.dart, which might be a good time to formalize the API.

Closing the client takes very long (60secs)

This code take quite a long time to end. Any hints what I'm doing wrong?

void runDbus()  async {
  var client = DBusClient.system();
  var object = DBusRemoteObject(client, 'org.freedesktop.ModemManager1',
        DBusObjectPath('/org/freedesktop/ModemManager1'));
  var values = <DBusValue>[];
    var response = await object.callMethod("org.freedesktop.DBus.ObjectManager",
        'GetManagedObjects', values);
    var result_array = response.returnValues;

  print('Closing');
  var f1 = client.close();
  await f1;
  print('Done');
}

Generate classes for returned structs

If a method call returns multiple values, we just expose this as a DBusStruct. It would be nice to make an object for these return values (might need an annotation to give it a name).

Generated getters and setters don't match

Generated read-write remote-object properties are broken. Async getters returning Future are not compatible with setters, that cannot be async, by the same name.

$ dart-dbus generate-remote-object org.freedesktop.NetworkManager.Device.xml # [1]

=>

  /// Gets org.freedesktop.NetworkManager.Device.Managed
  Future<bool> get Managed async {
    var value = await getProperty('org.freedesktop.NetworkManager.Device', 'Managed');
    return (value as DBusBoolean).value;
  }

  /// Sets org.freedesktop.NetworkManager.Device.Managed
  set Managed (bool value) {
    setProperty('org.freedesktop.NetworkManager.Device', 'Managed', DBusBoolean(value));
  }

=>

The return type of getter 'Managed' is 'Future' which isn't assignable to the type 'bool' of its setter 'Managed'. Try changing the types so that they are compatible.

[1] https://cgit.freedesktop.org/NetworkManager/NetworkManager/plain/introspection/org.freedesktop.NetworkManager.Device.xml

No example to demonstrate DBusSignalSubscription.

I am working on a plugin which fetches battery percentage and status from linux platform. It's dbus interface definition is :

<node name="/org/freedesktop/UPower/devices/DisplayDevice">
   <interface name="org.freedesktop.UPower.Device">
      <property name="Percentage" type="d" access="read" />
      <signal name="State" type="n" />
   </interface>
</node>

And generated dart file is :

import 'package:dbus/dbus.dart';

class OrgFreedesktopUPowerDevicesDisplayDevice extends DBusRemoteObject {
  OrgFreedesktopUPowerDevicesDisplayDevice(
      DBusClient client, String destination,
      {DBusObjectPath path = const DBusObjectPath.unchecked(
          '/org/freedesktop/UPower/devices/DisplayDevice')})
      : super(client, destination, path);

  /// Gets org.freedesktop.UPower.Device.Percentage
  Future<double> get percentage async {
    var value =
        await getProperty('org.freedesktop.UPower.Device', 'Percentage');
    return (value as DBusDouble).value;
  }

  /// Subscribes to org.freedesktop.UPower.Device.State
  Future<DBusSignalSubscription> subscribeState(
      void Function() callback) async {
    return await subscribeSignal('org.freedesktop.UPower.Device', 'State',
        (values) {
      if (values.length != 0) {
        callback();
      }
    });
  }
}

I want to return a Stream from plugin which states the status of battery in linux platform but can't find any documentation to implement it or a method to get it's value from generated subscribeState function.

No data recieved from subscribeSignal method.

With the help of example/signal.dart, I was able to write this function but still no value is being recieved from it.

var client = DBusClient.system();
var object = DBusRemoteObject(
  client,
  'org.freedesktop.UPower',
  DBusObjectPath('/org/freedesktop/UPower/devices/DisplayDevice'),
);
var stream = object.subscribeSignal('org.freedesktop.UPower.Device', 'State');
await for (var signal in stream) {
  var state = (signal.values[0] as DBusUint64).value;
  print('State is : $state!');
}

Null safety support

Hello! 👋

We use dbus on the Linux implementations of the battery_plus, connectivity_plus and network_info_plus Flutter packages, located here: https://github.com/fluttercommunity/plus_plugins, and we are currently migrating them to null safety.

Unfortunately this is blocking us.

Do you have any plans on migrating the package to null safety?

I am happy to help with the task. I will try to send you a PR with the changes I think are necessary, but I would definitely need your assistance.

Replace FFI getuid

It would be nice to not have the getuid FFI code and instead use some system library to do this.

Timeout Exception on Bus Reply.

Hi

I've been recently bitten by an update in DBus, as now it seems that syncronous DBus calls receive a Timeout from the server, in about 5 seconds.

The problem happens on Ubuntu 20.04 LTS, with a default install of flutter and dbus 0.5.x. This issue did not happen on dbus 0.3.x

I receive the following unexpected exception from the server:

org.freedesktop.Avahi.TimeoutError: TimeoutReached

As I traced back into my code, this happens when calling the method org.freedesktop.Avahi.Server.ResolveService using the avahi service files.
The stack trace is the following:

00:15 +0: external_api Able to create a discovery without D-Bus complaining    
Enabling workaround for V1 API with the 100ms wait behavior. Update your Avahi version to 0.8 or later if you want this warning to disappear.
00:17 +3: end-to-end Broadcast name and receive them on service enumeration    
Enabling workaround for V1 API with the 100ms wait behavior. Update your Avahi version to 0.8 or later if you want this warning to disappear.
Cached service received: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET6', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET6', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
Item added! AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET6', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET6', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
Cached service received: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
Item added! AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '2',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
Cached service received: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '1',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '1',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
Item added! AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '1',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
DBG: AvahiServiceBrowserItemNew(path: 'DBusObjectPath('/Client57/ServiceBrowser1')',interface: '1',protocol: 'AvahiProtocol.AVAHI_PROTO_INET', name: 'ItemNew',type: '_bonsoire2e._tcp',domain: 'local'
00:22 +3 -1: end-to-end Broadcast name and receive them on service enumeration [E]
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 49:13  LinuxDBusBonsoirDiscovery.ready.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _StreamImpl.listen
  package:dbus/src/dbus_client.dart 126:31                                DBusSignalStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 39:12  LinuxDBusBonsoirDiscovery.ready
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart 70:48                                 main.<fn>.<fn>
  test/bonsoir_linux_dbus_test.dart 61:68                                 main.<fn>.<fn>
  
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 84:7   LinuxDBusBonsoirDiscovery.start.<fn>
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:57  LinuxDBusBonsoirDiscovery.start.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _ForwardingStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:50  LinuxDBusBonsoirDiscovery.start
  test/bonsoir_linux_dbus_test.dart 121:50                                main.<fn>.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart                                       main.<fn>.<fn>
  
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 49:13  LinuxDBusBonsoirDiscovery.ready.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _StreamImpl.listen
  package:dbus/src/dbus_client.dart 126:31                                DBusSignalStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 39:12  LinuxDBusBonsoirDiscovery.ready
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart 70:48                                 main.<fn>.<fn>
  test/bonsoir_linux_dbus_test.dart 61:68                                 main.<fn>.<fn>
  
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 84:7   LinuxDBusBonsoirDiscovery.start.<fn>
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:57  LinuxDBusBonsoirDiscovery.start.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _ForwardingStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:50  LinuxDBusBonsoirDiscovery.start
  test/bonsoir_linux_dbus_test.dart 121:50                                main.<fn>.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart                                       main.<fn>.<fn>
  
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 49:13  LinuxDBusBonsoirDiscovery.ready.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _StreamImpl.listen
  package:dbus/src/dbus_client.dart 126:31                                DBusSignalStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 39:12  LinuxDBusBonsoirDiscovery.ready
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart 70:48                                 main.<fn>.<fn>
  test/bonsoir_linux_dbus_test.dart 61:68                                 main.<fn>.<fn>
  
  org.freedesktop.Avahi.TimeoutError: Timeout reached
  package:dbus/src/dbus_client.dart 1067:7                                DBusClient._callMethod
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncErrorWrapperHelper
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 84:7   LinuxDBusBonsoirDiscovery.start.<fn>
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:57  LinuxDBusBonsoirDiscovery.start.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _ForwardingStream.listen
  package:bonsoir_linux_dbus/src/linux_dbus_bonsoir_discovery.dart 76:50  LinuxDBusBonsoirDiscovery.start
  test/bonsoir_linux_dbus_test.dart 121:50                                main.<fn>.<fn>
  ===== asynchronous gap ===========================
  dart:async                                                              _asyncThenWrapperHelper
  test/bonsoir_linux_dbus_test.dart                                       main.<fn>.<fn>
  
00:23 +3 -1: Some tests failed.

My test file and entire source code is public at https://github.com/Piero512/bonsoir_linux_dbus

It seems like DBus is missing a timeout parameter for the method call and now that it parses the error messages correctly, this happens.

Unknown DBus data type on Flutter

Hi!

I was trying to interface with the NetworkManger via dbus to provide linux implementation for the flutter connectivity plugin.
The source code can be found here.
https://github.com/fluttercommunity/firebase_dart_sdk/blob/1dc2373b9524b8a429d6bad32a127eb497fc7b0f/connectivity_linux/lib/connectivity_linux.dart#L81

Note: This only happens when I run the flutter app. When I run it as a simple dart app everything worked well.

Thank you.

Distributor ID:	Ubuntu
Description:	Ubuntu 18.04.5 LTS
Release:	18.04
Codename:	bionic
Launching lib/main.dart on Linux in debug mode...
Building Linux application...
Waiting for Linux to report its views...
Debug service listening on ws://127.0.0.1:46223/qySq3Oyb90M=/ws
Syncing files to device Linux...
[ERROR:flutter/lib/ui/ui_dart_state.cc(171)] Unhandled Exception: Unknown DBus data type '5fc6b82c95f466712
l����   �   =   ��s �   :1.297  ��u �  �g �s  ��s �   org.freedesktop.DBus    '
#0      DBusReadBuffer.readDBusValue (package:dbus/src/dbus_read_buffer.dart:253:7)
#1      DBusReadBuffer.readDBusVariant (package:dbus/src/dbus_read_buffer.dart:160:22)
#2      DBusReadBuffer.readDBusValue (package:dbus/src/dbus_read_buffer.dart:239:14)
#3      DBusReadBuffer.readDBusStruct (package:dbus/src/dbus_read_buffer.dart:169:19)
#4      DBusReadBuffer.readDBusValue (package:dbus/src/dbus_read_buffer.dart:251:14)
#5      DBusReadBuffer.readDBusArray (package:dbus/src/dbus_read_buffer.dart:184:19)
#6      DBusMessage.unmarshal (package:dbus/src/dbus_message.dart:125:26)
#7      DBusClient._processMessages (package:dbus/src/dbus_client.dart:488:18)
#8      DBusClient._processData (package:dbus/src/dbus_client.dart:463:20)
#9      _rootRunUnary (dart:async/zone.dart:1198:47)
#10     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#11     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
#12     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#13     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
#14     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:808:19)
#15     _StreamController._add (dart:async/stream_controller.dart:682:7)
#16     _StreamController.add (dart:async/stream_controller.dart:624:5)
#17     _Socket._onData (dart:io-patch/socket_patch.dart:2043:41)
#18     _rootRunUnary (dart:async/zone.dart:1206:13)
#19     _CustomZone.runUnary (dart:async/zone.dart:1100:19)
#20     _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
#21     _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
#22     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7)
#23     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:808:19)
#24     _StreamController._add (dart:async/stream_controller.dart:682:7)
#25     _StreamController.add (dart:async/stream_controller.dart:624:5)
#26     new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1579:33)
#27     _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1075:14)
#28     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#29     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)

Replace callbacks with streams

Currently you register callbacks to handle signals:

var client = DBusClient.session();
var subscription = await client.subscribeSignals((path, interface, member, values) {
  var count = (values[0] as DBusUint64).value;
  print('Ping ${count}!');
}, sender: 'com.example.DartTest');
...
client.unsubscribeSignals();

I think the more Dart way of doing things is to use a stream, which would give an API like this:

var stream = await client.subscribeSignals(sender: 'com.example.DartTest');
await for (signal in stream) {
  var count = (signal.values[0] as DBusUint64).value;
  print('Ping ${count}!')
}

or with callbacks:

var stream = await client.subscribeSignals(sender: 'com.example.DartTest');
var subscription = stream.listen((signal) {
  var count = (signal.values[0] as DBusUint64).value;
  print('Ping ${count}!')
});
...
subscription.cancel();

Version

Any chance to bump the version to 0.0.1?

$ pub publish --dry-run
[foo_bar]: Publishing foo x.y.z to https://pub.dartlang.org:
[...]
[foo_bar]: Package validation found the following potential issue:
[foo_bar]: * Packages dependent on a pre-release of another package should themselves be published as a pre-release version. If this package needs dbus version 0.0.0-dev.23, consider publishing the package as a pre-release instead.
[foo_bar]:   See https://dart.dev/tools/pub/publishing#publishing-prereleases For more information on pre-releases.
[foo_bar]:
[foo_bar]: Package has 1 warning.

Support file descriptors

DBus is able to send file descriptors, however these are not supported in Dart. We should find a method of making these usable, possibly using an option FFI interface and/or by adding file descriptor support to Dart.

_read isolate never ends, which makes it impossible to close the app

Attempting to close my app makes it freeze, and after a couple of seconds spits out:

Attempt:12 waiting for isolate _read to check in
Attempt:13 waiting for isolate _read to check in
Attempt:14 waiting for isolate _read to check in
Attempt:15 waiting for isolate _read to check in
Attempt:16 waiting for isolate _read to check in
Attempt:17 waiting for isolate _read to check in
Attempt:18 waiting for isolate _read to check in
Attempt:19 waiting for isolate _read to check in
Attempt:20 waiting for isolate _read to check in
Attempt:21 waiting for isolate _read to check in
Attempt:22 waiting for isolate _read to check in
Attempt:23 waiting for isolate _read to check in
Attempt:24 waiting for isolate _read to check in
... (and so on)

Probably need to add a dispose/close method, or make it detect the app is exiting somehow
Also, it looks like it's waiting in the read method of UnixDomainSocket. Maybe closing the socket will make it exit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.