Unable to view events in the XProtect Smart Client UI.

I am trying to create AC Events by fetching data through API. The ToAcEvent Method gets executed correctly still I am unable to see the events on the UI. Same works when I fetch the events using the Pusher. The problem is that one of our customers doesn’t want to unblock the Pusher on their internal network. And if there any other way we can achieve showing the live events without using maybe using Pusher please let us know.

Here is our implementation of ToACEvent Method:

internal static ACEvent ToACEvent(MercuryEventData baseEvent)
{
    try
    {
        ACUtil.Log(false, "MERCURY MSAccessControlPlugin.TypeConverter", "Convert to AC Event started. " + baseEvent.Id);
        var eventId = baseEvent.Id;
        var eventTypeId = baseEvent.SequrCode;
 
        var relatedCredentialHolderIds = new List<string>();
        if (baseEvent.Actor?.User != null)
        {
            relatedCredentialHolderIds.Add(baseEvent.Actor.User.Uuid);
        }
 
        var sourceOperationableInstanceId = baseEvent.Door?.Uuid ?? baseEvent.MonitorPoint?.Uuid ?? baseEvent.ControlPoint?.Uuid;
 
        ACUtil.Log(false, "MSAccessControlPlugin.TypeConverter", $"EventId: {eventId}, EventTypeId: {eventTypeId}, sourceOperationableInstanceId: {sourceOperationableInstanceId}, eventTime: {baseEvent.Time}");
        return new ACEvent(eventId, eventTypeId, sourceOperationableInstanceId, baseEvent.Time, string.Empty, baseEvent.Message, relatedCredentialHolderIds, null, null);
    }
    catch (Exception ex)
    {
        ACUtil.Log(true, "MSAccessControlPlugin.TypeConverter", ex.Message + " " + ex.StackTrace);
    }
 
    return null;
}

Here’s how we are calling it while fetching data from API:

private async Task EventPollingAsync(CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        try
        {
            // Get events from the Demo Access Control system
            var events = await GetEvents(_systemProperties.APIKey, _systemProperties.LocationUuid.ToString(), _systemProperties.CustomerUuid);
 
            foreach (var baseEvent in events.Data ?? new List<MercuryEventData>())
            {
                if (baseEvent != null)
                {
                    var acEvent = TypeConverter.ToACEvent(baseEvent);
                    EventTriggered(this, new EventTriggeredEventArgs(acEvent));
                    continue;
                }
            }
        }
        catch (Exception ex)
        {
            ACUtil.Log(true, logTag, "Event polling to Genea failed: " + ex.Message + " " + ex.StackTrace);
        }
 
        try
        {
            await Task.Delay(60000, cancellationToken);
        }
        catch (OperationCanceledException) { }
    }
}

And here’s how we process the event received in Pusher:

private void ProcessMercuryEventMessage(dynamic data)
{
    try
    {
        JObject attributesAsJObject = data;
        var values = attributesAsJObject.ToObject<EventTriggeredEventModel>();
        ACUtil.Log(false, logTag, $"access_logs_updated event eventData: {JsonConvert.SerializeObject(values)}");
        var eventData = JsonConvert.DeserializeObject<MercuryEventTriggeredModel>(values.Data);
        EventTriggered(this, new EventTriggeredEventArgs(Configuration.TypeConverter.ToACEvent(new MercuryEventData()
        {
            Id = eventData.Message.Id,
            Actor = (!string.IsNullOrWhiteSpace(eventData.Message.Actor?.Type) && eventData.Message.Actor.Type.Equals("User", StringComparison.OrdinalIgnoreCase)) ? new ResponseModels.Mercury.Actor()
            {
                User = new EventUser()
                {
                    Uuid = eventData.Message.Actor.User.Uuid,
                    Name = eventData.Message.Actor.User.Name
                }
            } : null,
            Door = (!string.IsNullOrWhiteSpace(eventData.Message.Door?.Uuid)) ? new ResponseModels.Mercury.Door()
            {
                Uuid = eventData.Message.Door.Uuid,
                Name = eventData.Message.Door.Name
            } : null,
            MonitorPoint = (!string.IsNullOrWhiteSpace(eventData.Message.MonitorPoint?.Uuid)) ? new ResponseModels.Mercury.MonitorPoint()
            {
                Uuid = "MP_" + eventData.Message.MonitorPoint.Uuid,
                Name = eventData.Message.MonitorPoint.Name
            } : null,
            ControlPoint = (!string.IsNullOrWhiteSpace(eventData.Message.ControlPoint?.Uuid)) ? new ResponseModels.Mercury.ControlPoint()
            {
                Uuid = "CP_" + eventData.Message.ControlPoint.Uuid,
                Name = eventData.Message.ControlPoint.Name
            } : null ,
            SequrCode = eventData.Message.SequrCode,
            Time = eventData.Message.Time,
            Message = eventData.Message.Message,
        })));
    }
    catch (Exception ex)
    {
        ACUtil.Log(true, logTag, "access_logs_updated event error: " + ex.Message);
    }
}

While the ToAcEvent gets called for processing the Events fetched from the API we can see in the logs that the events get converted to ACEvents successfully:

Also in the configuration all the events have been mapped to proper Event Categories:

We won’t to know what we are missing out and whether what we are trying to achieve is possible or not.

Hello Vishal,

The code seems correct, so I am surprised that it doesn’t work with the API calls. The only thing I can think of, that can be the reason for this behaviour, is if nothing is subscribed to the “EventTriggered” event for the API calls. Can you try and see if the “FireEventsOccurred” gets called from your implementation of the ACEventManager abstract class when you do the event polling?

Also I’d like to know where you look for the events? Is in the Access Control Workspace in the Smart Client?

Hey Georgi,

Thank you so much for your response. You were right. The FireEventsOccurred method was not being called while creating event through event polling. Now it seems to be working fine.

Yes you are right, Under the Access Control in the Smart Client