Skip to content

Commit aca91f2

Browse files
committed
feat: get specific device types for channel
1 parent 3238727 commit aca91f2

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/Atc.Kepware.Configuration/Services/Connectivity/KepwareConfigurationClientConnectivity.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// ReSharper disable ParameterTypeCanBeEnumerable.Local
22
// ReSharper disable CheckNamespace
3+
using System.Reflection;
4+
using System.Text.Json.Nodes;
5+
36
namespace Atc.Kepware.Configuration.Services;
47

58
/// <summary>
@@ -206,6 +209,67 @@ public async Task<HttpClientRequestResult<bool>> IsTagGroupDefined(
206209
return response.Adapt<HttpClientRequestResult<IList<DeviceBase>?>>();
207210
}
208211

212+
public async Task<HttpClientRequestResult<IList<TDevice>?>> GetDevicesByChannelName<TDevice>(
213+
string channelName,
214+
CancellationToken cancellationToken)
215+
where TDevice : DeviceBase
216+
{
217+
ArgumentNullException.ThrowIfNull(channelName);
218+
219+
if (!IsValidConnectivityName(
220+
channelName,
221+
deviceName: null,
222+
tagGroupNameOrTagName: null,
223+
tagGroupStructure: null,
224+
out var errorMessage))
225+
{
226+
return await Task.FromResult(HttpClientRequestResultFactory<IList<TDevice>?>.CreateBadRequest(errorMessage!));
227+
}
228+
229+
var response = await Get<IList<JsonObject>>(
230+
$"{EndpointPathTemplateConstants.Channels}/{channelName}/{EndpointPathTemplateConstants.Devices}",
231+
cancellationToken);
232+
233+
// TODO: Handle properly and return HttpClientRequestResult<...>
234+
if (!response.HasData)
235+
{
236+
throw new Exception("No data returned!");
237+
}
238+
239+
// Get the implemented interfaces that derive from IDeviceBase, but are not IDeviceBase
240+
// TODO: Cache
241+
ISet<Type> implementedInterfaces = typeof(TDevice)
242+
.GetInterfaces()
243+
.Where(x
244+
=> typeof(IDeviceBase).IsAssignableFrom(x)
245+
&& x != typeof(IDeviceBase))
246+
.ToHashSet();
247+
248+
// Find the first type in this assembly that share an interface
249+
// TODO: Cache
250+
Type mappingType = Assembly
251+
.GetExecutingAssembly()
252+
.GetTypes()
253+
.First(x => x
254+
.GetInterfaces()
255+
.Any(y => implementedInterfaces.Contains(y)));
256+
257+
// Serialize JSON to internal type and adapt to destination type
258+
IList<object?> internalDeviceTypes = response
259+
.Data
260+
.Select(x => JsonSerializer.Deserialize(x.ToString(), mappingType))
261+
.ToList();
262+
Type deviceTypeListType = typeof(IList<>).MakeGenericType(typeof(TDevice));
263+
IList<TDevice>? deviceTypes = (IList<TDevice>?)internalDeviceTypes.Adapt(typeof(IList<object?>), deviceTypeListType);
264+
265+
return new HttpClientRequestResult<IList<TDevice>?>(deviceTypes)
266+
{
267+
CommunicationSucceeded = response.CommunicationSucceeded,
268+
StatusCode = response.StatusCode,
269+
Message = response.Message,
270+
};
271+
}
272+
209273
public async Task<HttpClientRequestResult<TagRoot>> GetTags(
210274
string channelName,
211275
string deviceName,

0 commit comments

Comments
 (0)