Skip to content

Commit 0b7315c

Browse files
authored
Merge pull request #22 from michielpost/feature/event-monitor
Event Monitor and Resource Explorer
2 parents 840c0aa + 6a864cc commit 0b7315c

File tree

210 files changed

+1728
-28725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

210 files changed

+1728
-28725
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using HueEntertainmentPro.Database;
2+
using HueEntertainmentPro.Database.Models;
3+
using Microsoft.EntityFrameworkCore;
4+
5+
namespace HueEntertainmentPro.Services
6+
{
7+
public class BridgeService(HueEntertainmentProDbContext dbContext)
8+
{
9+
10+
public async Task<Bridge?> GetBridge(Guid id)
11+
{
12+
var bridge = await dbContext.Bridges.Where(x => x.Id == id).FirstOrDefaultAsync();
13+
if (bridge == null)
14+
return null;
15+
16+
return bridge;
17+
}
18+
19+
}
20+
}

HueEntertainmentPro/Client/HueEntertainmentPro.Client.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="HueApi" Version="3.0.0" />
1314
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.9" />
1415
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.9" PrivateAssets="all" />
1516
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="9.0.9" />

HueEntertainmentPro/Client/Layout/MainLayout.razor

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
<FluentDialogProvider />
2929
<FluentTooltipProvider />
3030
<FluentMessageBarProvider />
31+
<FluentMenuProvider />
3132
<FluentDesignTheme StorageName="theme" />
3233
</FluentLayout>

HueEntertainmentPro/Client/Layout/NavMenu.razor

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,23 @@
33
<label for="navmenu-toggle" class="navmenu-icon"><FluentIcon Value="@(new Icons.Regular.Size20.Navigation())" Color="Color.Fill" /></label>
44
<nav class="sitenav" aria-labelledby="main-menu">
55
<FluentNavMenu Id="main-menu" Width="250" Collapsible="true" Title="Navigation menu" @bind-Expanded="expanded" CustomToggle="true">
6-
<FluentNavLink Href="/" Match="NavLinkMatch.All" Icon="@(new Icons.Regular.Size20.Home())" IconColor="Color.Accent">Home</FluentNavLink>
6+
<FluentNavLink Href="/" Match="NavLinkMatch.All" Icon="@(new Icons.Regular.Size20.Home())" IconColor="Color.Accent">Home</FluentNavLink>
77
<FluentNavLink Href="bridges" Icon="@(new Icons.Regular.Size20.Iot())" IconColor="Color.Accent">Bridges</FluentNavLink>
8-
<FluentNavLink Href="settings" Icon="@(new Icons.Regular.Size20.Settings())" IconColor="Color.Accent">Settings</FluentNavLink>
8+
<FluentNavLink Href="eventmonitor" Icon="@(new Icons.Regular.Size20.EarthLeaf())" IconColor="Color.Accent">Event Monitor</FluentNavLink>
9+
<FluentNavLink Href="resource-explorer" Icon="@(new Icons.Regular.Size20.ServerMultiple())" IconColor="Color.Accent">Resource Explorer</FluentNavLink>
10+
<FluentNavLink Href="settings" Icon="@(new Icons.Regular.Size20.Settings())" IconColor="Color.Accent">Settings</FluentNavLink>
911
</FluentNavMenu>
1012

1113

12-
14+
1315

1416
</nav>
1517
</div>
1618

1719
@code {
1820
private bool expanded = true;
1921

20-
2122

22-
23+
24+
2325
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using HueApi.Models;
2+
3+
namespace HueEntertainmentPro.Client.Models
4+
{
5+
public class ExtensionDataPanelViewModel
6+
{
7+
public HueResource HueResource { get; set; } = default!;
8+
public HueEntertainmentPro.Shared.Models.Bridge? Bridge { get; set; }
9+
}
10+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
@page "/eventmonitor"
2+
@using HueEntertainmentPro.Client.Services
3+
@using HueEntertainmentPro.Shared.Interfaces
4+
@using HueEntertainmentPro.Shared.Models
5+
@inject IBridgeDataService BridgeDataService
6+
@inject NavigationManager Navigation
7+
@inject IDialogService DialogService
8+
@inject EventMonitorService EventMonitorService
9+
@inject ResourceExplorerService ResourceExplorerService
10+
11+
<PageTitle>Event Monitor</PageTitle>
12+
13+
<h1>Event Monitor</h1>
14+
15+
<p>Monitor all events from a bridge. Select a bridge and click Connect.</p>
16+
17+
@if (bridges == null)
18+
{
19+
<p><em>Loading bridges...</em></p>
20+
}
21+
else
22+
{
23+
<FluentGrid Spacing="3" AdaptiveRendering="true" Justify="JustifyContent.FlexStart" Style="padding: 4px; ">
24+
<FluentGridItem xs="12">
25+
<FluentTabs Orientation="Orientation.Vertical">
26+
@foreach (var item in bridges)
27+
{
28+
<FluentTab Id="@($"tab-{item.Id}")"
29+
Data="@item">
30+
<Header>
31+
<FluentLabel Typo="Typography.Header">@item.Name (@item.Ip)</FluentLabel>
32+
</Header>
33+
<Content>
34+
@if (!subscribedBridges.Contains(item.Id))
35+
{
36+
<FluentButton OnClick="() => Subscribe(item.Id)">Connect</FluentButton>
37+
}
38+
else
39+
{
40+
<FluentButton OnClick="() => Unsubscribe(item.Id)">Disconnect</FluentButton>
41+
}
42+
<FluentDataGrid Items="@events.Where(x => x.BridgeIp == item.Ip).OrderByDescending(x => x.CreationTime).ThenByDescending(x => x.SendTime).Take(100).AsQueryable()" ResizableColumns=true Style="width: 100%;" AutoFit="true">
43+
44+
<PropertyColumn Sortable="true" Property="x => x.CreationTime" Title="Time" />
45+
<PropertyColumn Property="x => x.BridgeIp" Title="IP" />
46+
47+
<PropertyColumn Property="x => x.Type" Title="Type" />
48+
49+
<TemplateColumn Title="Id">
50+
<NavLink href="@ResourceExplorerService.CreateResourceLink(item.Id, context.Type, context.Id)">@context.Id</NavLink>
51+
</TemplateColumn>
52+
53+
@if (events.Where(x => x.EventDetails.Name != null).Any())
54+
{
55+
<PropertyColumn Property="x => x.EventDetails.Name" Title="Name" />
56+
}
57+
58+
@if (events.Where(x => x.EventDetails.IdV1 != null).Any())
59+
{
60+
<PropertyColumn Property="x => x.EventDetails.IdV1" Title="Name" />
61+
}
62+
63+
<TemplateColumn Title="Data">
64+
<ul>
65+
@foreach (var kvp in context.EventDetails.ExtensionData)
66+
{
67+
<li>@kvp.Key: @kvp.Value</li>
68+
}
69+
</ul>
70+
</TemplateColumn>
71+
</FluentDataGrid>
72+
</Content>
73+
</FluentTab>
74+
}
75+
</FluentTabs>
76+
</FluentGridItem>
77+
</FluentGrid>
78+
79+
80+
}
81+
82+
83+
@code {
84+
85+
private IQueryable<Bridge>? bridges;
86+
87+
private string bridgeIdInput = string.Empty;
88+
private string status = "Not subscribed";
89+
private List<EventData> events = new();
90+
91+
private List<Guid> subscribedBridges = new();
92+
93+
protected override async Task OnInitializedAsync()
94+
{
95+
var result = await BridgeDataService.GetBridges();
96+
bridges = result.AsQueryable();
97+
98+
EventMonitorService.OnSubscribed += (message) =>
99+
{
100+
subscribedBridges.Add(message);
101+
Console.WriteLine();
102+
status = $"Subscribed: {message}";
103+
StateHasChanged();
104+
};
105+
106+
EventMonitorService.OnUnsubscribed += (message) =>
107+
{
108+
subscribedBridges.Remove(message);
109+
status = $"Unsubscribed: {message}";
110+
StateHasChanged();
111+
};
112+
113+
EventMonitorService.OnError += (message) =>
114+
{
115+
status = $"Error: {message}";
116+
StateHasChanged();
117+
};
118+
119+
EventMonitorService.OnEventReceived += (eventData) =>
120+
{
121+
events.Add(eventData);
122+
StateHasChanged();
123+
};
124+
}
125+
126+
private async Task Subscribe(Guid bridgeId)
127+
{
128+
await EventMonitorService.SubscribeAsync(bridgeId);
129+
status = $"Subscribing to bridge: {bridgeId}";
130+
131+
StateHasChanged();
132+
}
133+
134+
private async Task Unsubscribe(Guid bridgeId)
135+
{
136+
await EventMonitorService.UnsubscribeAsync(bridgeId);
137+
status = "Unsubscribing...";
138+
StateHasChanged();
139+
}
140+
141+
public async ValueTask DisposeAsync()
142+
{
143+
await EventMonitorService.DisposeAsync();
144+
}
145+
}

0 commit comments

Comments
 (0)