Skip to content
This repository has been archived by the owner on Oct 9, 2023. It is now read-only.

Mediator agent InboxItemEvent #181

Open
juvebogdan opened this issue Apr 3, 2021 · 10 comments
Open

Mediator agent InboxItemEvent #181

juvebogdan opened this issue Apr 3, 2021 · 10 comments

Comments

@juvebogdan
Copy link

Hello,

Can someone please give some guidance on how to use InboxItemEvent to implement push notifications. Is InboxId field that identifies Edge agent? At what point i cn hook into and tie this filed to notification token?

Thank you

@sahil-khanna
Copy link

@juvebogdan,

You can search for the Push Token from walletRecordService.SearchAsync<DeviceInfoRecord>. Use the search query for inboxItemEvent.InboxId. This will list the DeviceInfoRecords from where you can get the DeviceId

@mat-work
Copy link

One more possible issue.
Push tokens can change over time for different reasons (app upgrade, etc..).

It seems that RoutingInboxHandler returns a WalletItemAlreadyExistsException when invoking AddDeviceInfoAsync

https://github.com/hyperledger/aries-framework-dotnet/blob/ee0ec833ff80f166fd1250dcd49f1e223ef964c0/src/Hyperledger.Aries.Routing.Mediator/Handlers/RoutingInboxHandler.cs#L83

Could anybody confirm this is the case?
Maybe it should update the record instead?

TIA

@sahil-khanna
Copy link

One more possible issue.
Push tokens can change over time for different reasons (app upgrade, etc..).

It seems that RoutingInboxHandler returns a WalletItemAlreadyExistsException when invoking AddDeviceInfoAsync

https://github.com/hyperledger/aries-framework-dotnet/blob/ee0ec833ff80f166fd1250dcd49f1e223ef964c0/src/Hyperledger.Aries.Routing.Mediator/Handlers/RoutingInboxHandler.cs#L83

Could anybody confirm this is the case?
Maybe it should update the record instead?

TIA

@mat-work, from what I have been doing so far is as described below. It works without any issue.

  • You need to AddDeviceInfoMessage from the Edge Agent whenever the Push Notification Token is updated. This will add a new entry in the Mediator Agent for the connection
AddDeviceInfoMessage deviceInfoMessage = new()
{
    DeviceId = token,
    DeviceVendor = DeviceInfo.Platform.ToString()
};

await edgeClientService.AddDeviceAsync(agentContext, deviceInfoMessage);
  • On the Mediator Agent, get the most recent DeviceInfoRecord (sort by CreatedAtUtc.Value) and use that to send the Push Notification

@Drilmo
Copy link

Drilmo commented Jul 16, 2021

Hello @sahil-khanna

I'm sorry but I'm lost in the implementation of push notifications.

Do you have a concrete example of use? a tutorial?

Indeed I do not know where to place the portion of code that you have indicated above in the mediator.

(I use the mediator contained in the repository: https://github.com/hyperledger/aries-mobile-agent-xamarin)

Thanks in advance for your answer

@sahil-khanna
Copy link

sahil-khanna commented Aug 18, 2021

@Drilmo ,

You can try the below code. Replace it with this line

IHost Container = CreateHostBuilder(args).Build();

var eventAggregator = (IEventAggregator)Program.Container.Services.GetService(typeof(IEventAggregator));
_ = eventAggregator.GetEventByType<InboxItemEvent>().Subscribe(inboxItemEvent =>
{
   // Get the device token
   await walletRecordService.SearchAsync<DeviceInfoRecord>(
                wallet: agentContext.Wallet,
                query: SearchQuery.Equal(nameof(DeviceInfoRecord.InboxId), inboxItemEvent.InboxId.ToString()),
                count: int.MaxValue);
   Console.WriteLine(deviceInfoRecords.First().DeviceId);

   // Send Push Notification. The DeviceId is the token of the device
});

Container.Run();

@Drilmo
Copy link

Drilmo commented Aug 18, 2021

@Drilmo ,

You can try the below code. Place it just below this line

eventAggregator = (IEventAggregator)Program.Container.Services.GetService(typeof(IEventAggregator));

_ = eventAggregator.GetEventByType<InboxItemEvent>().Subscribe(inboxItemEvent =>
{
   // Get the device token
   await walletRecordService.SearchAsync<DeviceInfoRecord>(
                wallet: agentContext.Wallet,
                query: SearchQuery.Equal(nameof(DeviceInfoRecord.InboxId), inboxItemEvent.InboxId.ToString()),
                count: int.MaxValue);
   Console.WriteLine(deviceInfoRecords.First().DeviceId);

   // Send Push Notification. The DeviceId is the token of the device
});

@sahil-khanna, thank you very much for your answer!

Is it possible to set up 1 notification per type of event? if yes how to manage them?

I'm sorry for these questions but I'm completely lost with this mediator.

Thank you for your help.

@sahil-khanna
Copy link

sahil-khanna commented Aug 18, 2021

@Drilmo ,
You can try the below code. Place it just below this line

eventAggregator = (IEventAggregator)Program.Container.Services.GetService(typeof(IEventAggregator));

_ = eventAggregator.GetEventByType<InboxItemEvent>().Subscribe(inboxItemEvent =>
{
   // Get the device token
   await walletRecordService.SearchAsync<DeviceInfoRecord>(
                wallet: agentContext.Wallet,
                query: SearchQuery.Equal(nameof(DeviceInfoRecord.InboxId), inboxItemEvent.InboxId.ToString()),
                count: int.MaxValue);
   Console.WriteLine(deviceInfoRecords.First().DeviceId);

   // Send Push Notification. The DeviceId is the token of the device
});

@sahil-khanna, thank you very much for your answer!

Is it possible to set up 1 notification per type of event? if yes how to manage them?

I'm sorry for these questions but I'm completely lost with this mediator.

Thank you for your help.

@Drilmo, I doubt this can be done. The Mediator Agent cannot read the contents of the payload as the payload is encrypted. All it knows is the source and the recipient of the payload. Hence, you can send a common message for all the events the Mediator Agent receives.

@Drilmo
Copy link

Drilmo commented Aug 30, 2021

This code works in mediator :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Hyperledger.Aries.Contracts;
using Hyperledger.Aries.Routing;
using Hyperledger.Aries.Storage;
using Hyperledger.Aries.Agents;
using System.Net.Http;
namespace mediator 
{
    public class Program 
    {
        private static HttpClient client = new HttpClient();
        public static async Task Main(string[] args)
        {
            IHost Container = CreateHostBuilder(args).Build();
            var eventAggregator = (IEventAggregator)Container.Services.GetService(typeof(IEventAggregator));
            _ = eventAggregator.GetEventByType<InboxItemEvent>().Subscribe(async inboxItemEvent => 
            {
                // Get the device token
                var walletRecordService = (IWalletRecordService)Container.Services.GetService(typeof(IWalletRecordService));
                var agentProvider = (IAgentProvider)Container.Services.GetService(typeof(IAgentProvider));
                var agentContext = await agentProvider.GetContextAsync();
                List<DeviceInfoRecord> deviceInfoRecords = await walletRecordService.SearchAsync<DeviceInfoRecord>(
                                wallet: agentContext.Wallet,
                                query: SearchQuery.Equal(nameof(DeviceInfoRecord.InboxId), inboxItemEvent.InboxId.ToString()),
                                count: int.MaxValue);
                if (deviceInfoRecords.Any()){
                    Console.WriteLine("Push Token : " + deviceInfoRecords.First().DeviceId);
                    Console.WriteLine("Mobile Platform : " + deviceInfoRecords.First().DeviceVendor);
                    // Send Push Notification.                 
                }
            });
            Container.Run();
        }
    }
}

@naman20sharma
Copy link

  • You need to AddDeviceInfoMessage from the Edge Agent whenever the Push Notification Token is updated. This will add a new entry in the Mediator Agent for the connection
AddDeviceInfoMessage deviceInfoMessage = new()
{
    DeviceId = token,
    DeviceVendor = DeviceInfo.Platform.ToString()
};

await edgeClientService.AddDeviceAsync(agentContext, deviceInfoMessage);
  • On the Mediator Agent, get the most recent DeviceInfoRecord (sort by CreatedAtUtc.Value) and use that to send the Push Notification

Hi @sahil-khanna ,

Can you please guide me with this, I have some doubts:

  1. Where should we add these line of code in the Mobile wallet code ?

  2. Can we implement 3rd party Push notification service like Google Firebase here ?

  3. Do we still require to call FetchInboxAsync in Mobile code to process the messages from Mediator, if Push notification is successfully implemented ?

@sahil-khanna
Copy link

@naman20sharma, below are my responses to your questions.

  1. Where should we add these line of code in the Mobile wallet code ?
    A: You need to add the code at the Token Refresh event of the Push Notification. Refer to the example below.
  CrossPushNotification.Current.OnTokenRefresh += (s,p) =>
  {
        AddDeviceInfoMessage deviceInfoMessage = new()
        {
            DeviceId = p.Token,
            DeviceVendor = DeviceInfo.Platform.ToString()
        };

        await edgeClientService.AddDeviceAsync(agentContext, deviceInfoMessage);
  };
  1. Can we implement 3rd party Push notification service like Google Firebase here ?
    A. Yes. You may check out the Push Notification Plugin for Xamarin forms. It supports Firebase Cloud Messaging

  2. Do we still require to call FetchInboxAsync in Mobile code to process the messages from Mediator, if Push notification is successfully implemented ?
    A. Probably yes. Below are a few reasons.

  • Push Notifications are not reliable, i.e., they may fail
  • The user may turn off Push Notifications from the device settings (or by turning on Battery Saver)

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

No branches or pull requests

5 participants