Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to raise an event/signal? #62

Closed
dodgyrabbit opened this issue Sep 21, 2018 · 3 comments
Closed

How to raise an event/signal? #62

dodgyrabbit opened this issue Sep 21, 2018 · 3 comments

Comments

@dodgyrabbit
Copy link
Contributor

dodgyrabbit commented Sep 21, 2018

All of the examples/code I could find seem to show how you could create a proxy object and subscribe to signals that the remote object raises. I.e. consume events/signals.

How do I publish a local object that raises a signal?

await connection.RegisterObjectAsync(myObject);

I need to raise the PropertiesChanged signal for myObject and pass some values through in a dictionary.

Any help greatly appreciated.

@tmds
Copy link
Owner

tmds commented Sep 26, 2018

Did you get this to work?

@dodgyrabbit
Copy link
Contributor Author

Yes, I managed to get it to work. I've posted my minimal example here, in case it helps someone in the future. If you run it, you can use sudo busctl monitor and you should see the temperature signal going up every second.

I think I had a bit of a fundamental misunderstanding how DBus properties are modeled. I thought that if a DBus interface called for a list of properties, you would model that directly in your C# DBus Interface. It seems like the idea is that instead you expose the methods in the interface as defined by DBus called org.freedesktop.DBus.Properties and all properties of your object are accessed via these methods. You are then free to implement the properties as a different object (as shown in the examples) or I guess as part of your derived concrete class itself (as shown below).

There does seem to be something special with the WatchPropertiesAsync method. It automatically creates a signal called PropertiesChanged. If you called it WatchPropertiesChangedAsync, the signal is still called PropertiesChanged. Perhaps some kind of convenience feature? Or did I miss something in the docs? It you call it anything else, like WatchWeatherAsync, the signal that is emited is just called Weather.

In the unit test code, there is the org.freedesktop.DBus.Properties Interface definition (IPropertyObject.cs). It almost seems like that should be a standard interfaces in Tmds.DBus?

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Tmds.DBus;

[assembly: InternalsVisibleTo(Tmds.DBus.Connection.DynamicAssemblyName)]
namespace publishproperty
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Run(async () =>
            {
                using (var connection = new Connection(Address.System))
                {
                    await connection.ConnectAsync();
                    var exposed = new Example();
                    await connection.RegisterObjectAsync(exposed);

                    int globalWarming = 0;
                    while (true)
                    {
                        // Setting this value will create a signal on the bus with the new temperature value
                       exposed.Value = globalWarming++;
                       await Task.Delay(TimeSpan.FromSeconds(1));
                    }
                }
            }).Wait();
        }
    }

    public class Example : ITemperature
    {
        int _value;
        public int Value
         {
             get { return _value; }
             set 
             {
                 _value = value;
                 OnPropertiesChanged?.Invoke(PropertyChanges.ForProperty(nameof(Value), value));
             }
        }
        public ObjectPath ObjectPath => new ObjectPath("/com/example/object1");
        public event Action<PropertyChanges> OnPropertiesChanged;

        public Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler)
        {
            return SignalWatcher.AddAsync(this, nameof(OnPropertiesChanged), handler);
        }
    }
    [DBusInterface("com.example")]
    interface ITemperature : IDBusObject
    {
        Task<IDisposable> WatchPropertiesAsync(Action<PropertyChanges> handler);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants