Skip to content

Commit 04d946b

Browse files
committed
Merge branch 'feature/servers'
2 parents b9e2ed0 + 951762c commit 04d946b

22 files changed

+289
-208
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ jobs:
1010
- name: Setup .NET
1111
uses: actions/setup-dotnet@v1
1212
with:
13-
dotnet-version: '7.0.x'
13+
dotnet-version: '8.0.x'
1414

1515
- name: Clone Plugins
1616
uses: actions/checkout@v2
1717

1818
- name: Build Plugin
19-
run: dotnet publish -c Release src/Artemis.Plugins.Mqtt.sln
19+
run: dotnet publish -c Release src
2020

2121
- name: Upload
2222
uses: actions/upload-artifact@v2
2323
with:
2424
name: Artemis.Plugins.Mqtt
25-
path: src/Artemis.Plugins.Mqtt/bin/x64/Release/net7.0/publish
25+
path: src/Artemis.Plugins.Mqtt/bin/x64/Release/net8.0/publish

src/Artemis.Plugins.Mqtt.sln

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
Microsoft Visual Studio Solution File, Format Version 12.00
33
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Plugins.Mqtt", "Artemis.Plugins.Mqtt\Artemis.Plugins.Mqtt.csproj", "{C49EFF75-D1D3-486D-BA37-DF65481EA6EB}"
44
EndProject
5+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC333B86-D4D6-4D67-B713-293CAAAD0A1F}"
6+
ProjectSection(SolutionItems) = preProject
7+
..\.github\workflows\build.yml = ..\.github\workflows\build.yml
8+
EndProjectSection
9+
EndProject
510
Global
611
GlobalSection(SolutionConfigurationPlatforms) = preSolution
712
Debug|Any CPU = Debug|Any CPU

src/Artemis.Plugins.Mqtt/Artemis.Plugins.Mqtt.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
<TargetFramework>net8.0</TargetFramework>
44
<Platforms>x64</Platforms>
55
<EnableDynamicLoading>true</EnableDynamicLoading>
6+
<Nullable>enable</Nullable>
67
</PropertyGroup>
78

89
<ItemGroup>
9-
<PackageReference Include="ArtemisRGB.UI.Shared" IncludeAssets="compile;build;buildTransitive" Version="1.2024.225.6" />
10+
<PackageReference Include="ArtemisRGB.UI.Shared" IncludeAssets="compile;build;buildTransitive" Version="1.2024.302.1" />
1011
<PackageReference Include="MQTTnet" Version="4.3.3.952" />
1112
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.3.3.952" />
1213
</ItemGroup>

src/Artemis.Plugins.Mqtt/DataModels/MqttDataModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ public class MqttDataModel : DataModel
88
public StatusesDataModel Statuses { get; } = new();
99

1010
public NodeDataModel Root { get; } = new(new());
11+
12+
public MqttServersDataModel Servers { get; } = new();
1113
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.Linq;
6+
using Artemis.Core.Modules;
7+
using Swan;
8+
9+
namespace Artemis.Plugins.Mqtt.DataModels;
10+
11+
public class MqttNodeDataModel : DataModel
12+
{
13+
public string Data { get; set; }
14+
15+
public MqttNodeDataModel()
16+
{
17+
Data = "";
18+
}
19+
20+
public void PropagateValue(string[] topics, object data)
21+
{
22+
if (topics.Length == 0)
23+
{
24+
Data = data.ToString() ?? "";
25+
return;
26+
}
27+
28+
var key = topics[0];
29+
var remainingPartialTopics = topics[1..];
30+
if (!TryGetDynamicChild<MqttNodeDataModel>(key, out var child))
31+
child = AddDynamicChild<MqttNodeDataModel>(key, new());
32+
33+
child.Value.PropagateValue(remainingPartialTopics, data);
34+
}
35+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Artemis.Core.Modules;
4+
5+
namespace Artemis.Plugins.Mqtt.DataModels;
6+
7+
public class MqttServersDataModel : DataModel
8+
{
9+
private readonly Dictionary<Guid, DynamicChild<MqttNodeDataModel>> _servers = new();
10+
11+
internal void CreateServers(IEnumerable<MqttConnectionSettings> servers)
12+
{
13+
ClearDynamicChildren();
14+
_servers.Clear();
15+
16+
foreach (var server in servers)
17+
{
18+
var id = server.ServerId.ToString();
19+
_servers.Add(
20+
server.ServerId,
21+
AddDynamicChild(id, new MqttNodeDataModel(), server.DisplayName)
22+
);
23+
}
24+
}
25+
26+
public void PropagateValue(Guid sourceServer, string topic, object data)
27+
{
28+
if (!_servers.TryGetValue(sourceServer, out var server))
29+
return;
30+
31+
var parts = topic.Split('/');
32+
server.Value.PropagateValue(parts, data);
33+
}
34+
}

src/Artemis.Plugins.Mqtt/DataModels/NodeDataModel.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
33
using Artemis.Core.Modules;
4-
using Artemis.Plugins.Mqtt.DataModels.Dynamic;
54

65
namespace Artemis.Plugins.Mqtt.DataModels;
76

@@ -18,6 +17,9 @@ internal void CreateStructure(StructureDefinitionNode dataModelStructure)
1817
ClearDynamicChildren();
1918
_allDynamicChildren.Clear();
2019

20+
if (dataModelStructure.Children == null)
21+
return;
22+
2123
foreach (var childDefinition in dataModelStructure.Children)
2224
{
2325
var id = GetNodeId(childDefinition.Server ?? Guid.NewGuid(), childDefinition.Topic);
@@ -67,7 +69,7 @@ public void PropagateValue(Guid sourceServer, string topic, object data)
6769
boolChild.Value = string.Compare(data.ToString(), "true", StringComparison.OrdinalIgnoreCase) == 0;
6870
return;
6971
case DynamicChild<string> stringChild:
70-
stringChild.Value = data.ToString();
72+
stringChild.Value = data.ToString()!;
7173
return;
7274
}
7375
}
Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Text.Json.Serialization;
34

4-
namespace Artemis.Plugins.Mqtt.DataModels.Dynamic;
5+
namespace Artemis.Plugins.Mqtt.DataModels;
56

67
/// <summary>
78
/// Class that defines a single node of the DataModel structure.
89
/// </summary>
910
public class StructureDefinitionNode
1011
{
12+
public StructureDefinitionNode(string label, Guid? server, string topic, Type? type, bool isGroup)
13+
{
14+
Label = label;
15+
Server = server;
16+
Topic = topic;
17+
AssemblyQualifiedTypeName = type?.AssemblyQualifiedName ?? "";
18+
Children = isGroup ? new List<StructureDefinitionNode>() : null;
19+
}
20+
1121
/// <summary>
1222
/// The display name this node will appear as in the Artemis Data Model.
1323
/// </summary>
@@ -22,23 +32,30 @@ public class StructureDefinitionNode
2232
/// The topic that can be used to set the value of this node.
2333
/// </summary>
2434
public string Topic { get; set; }
35+
36+
/// <summary>
37+
/// The type of value stored in this node.
38+
/// </summary>
39+
public string AssemblyQualifiedTypeName { get; set; }
2540

2641
/// <summary>
2742
/// The type of value stored in this node.
2843
/// </summary>
29-
public Type Type { get; set; }
44+
[JsonIgnore]
45+
public Type? Type => Type.GetType(AssemblyQualifiedTypeName);
46+
47+
/// <summary>
48+
/// Whether this node is a group or not.
49+
/// </summary>
50+
public bool IsGroup => Children != null;
3051

3152
/// <summary>
3253
/// Any children this node has.
3354
/// </summary>
34-
public List<StructureDefinitionNode> Children { get; set; }
55+
public List<StructureDefinitionNode>? Children { get; set; }
3556

3657
/// <summary>
3758
/// Returns a default root <see cref="StructureDefinitionNode" />.
3859
/// </summary>
39-
public static StructureDefinitionNode RootDefault => new()
40-
{
41-
Label = "Root",
42-
Children = new List<StructureDefinitionNode>()
43-
};
60+
public static StructureDefinitionNode RootDefault => new("Root", null, "", typeof(object), true);
4461
}

src/Artemis.Plugins.Mqtt/MqttConnector.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Threading.Tasks;
@@ -13,41 +13,42 @@ namespace Artemis.Plugins.Mqtt;
1313
/// </summary>
1414
public sealed class MqttConnector : IDisposable
1515
{
16-
private static readonly MqttFactory clientFactory = new();
17-
private readonly IManagedMqttClient client;
16+
private static readonly MqttFactory ClientFactory = new();
17+
private readonly IManagedMqttClient _client;
1818

1919
public MqttConnector()
2020
{
21-
client = clientFactory.CreateManagedMqttClient();
22-
client.ApplicationMessageReceivedAsync += OnClientMessageReceived;
23-
client.ConnectedAsync += OnClientConnected;
24-
client.DisconnectedAsync += OnClientDisconnected;
21+
_client = ClientFactory.CreateManagedMqttClient();
22+
_client.ApplicationMessageReceivedAsync += OnClientMessageReceived;
23+
_client.ConnectedAsync += OnClientConnected;
24+
_client.DisconnectedAsync += OnClientDisconnected;
2525
}
2626

2727
/// <summary>
2828
/// The ID of the server this connector is connected to.
2929
/// <para />
30-
/// Based on the 'ServerId' property from the settings object passed to <see cref="Start(MqttConnectionSettings)" />.
30+
/// Based on the 'ServerId' property from the settings object passed to <see cref="Start(MqttConnectionSettings,IEnumerable{string})" />.
3131
/// </summary>
3232
public Guid ServerId { get; private set; }
3333

3434
/// <summary>
3535
/// Whether or not this connector is currently connected to a server.
3636
/// </summary>
37+
// ReSharper disable once UnusedAutoPropertyAccessor.Global
3738
public bool IsConnected { get; private set; }
3839

3940
public void Dispose()
4041
{
41-
client.Dispose();
42+
_client.Dispose();
4243
}
4344

4445
/// <summary>
4546
/// Event that fires when this connector receives a message from the server it is connected to.
4647
/// </summary>
47-
public event EventHandler<MqttApplicationMessageReceivedEventArgs> MessageReceived;
48+
public event EventHandler<MqttApplicationMessageReceivedEventArgs>? MessageReceived;
4849

49-
public event EventHandler<MqttClientConnectedEventArgs> Connected;
50-
public event EventHandler<MqttClientDisconnectedEventArgs> Disconnected;
50+
public event EventHandler<MqttClientConnectedEventArgs>? Connected;
51+
public event EventHandler<MqttClientDisconnectedEventArgs>? Disconnected;
5152

5253
/// <summary>
5354
/// Sets up and starts listening with the MQTT client behind this connector.
@@ -75,19 +76,20 @@ public async Task Start(MqttConnectionSettings settings, IEnumerable<string> top
7576
.WithClientOptions(clientOptions.Build())
7677
.Build();
7778

78-
await client.StopAsync();
79-
await client.StartAsync(managedClientOptions);
79+
await _client.StopAsync();
80+
await _client.StartAsync(managedClientOptions);
8081
await Task.WhenAll(
81-
topics.Select(topic => client.SubscribeAsync(topic))
82+
topics.Where(t => !string.IsNullOrWhiteSpace(t)).Select(topic => _client.SubscribeAsync(topic))
8283
);
84+
await _client.SubscribeAsync("#");
8385
}
8486

8587
/// <summary>
8688
/// Disconnects the connector from the server it is connected to.
8789
/// </summary>
8890
public Task Stop()
8991
{
90-
return client.StopAsync();
92+
return _client.StopAsync();
9193
}
9294

9395
private Task OnClientMessageReceived(MqttApplicationMessageReceivedEventArgs e)

0 commit comments

Comments
 (0)