DEV Community

Rido
Rido

Posted on • Originally published at blog.rido.dev

2 2

DTDL Parser extensions

The DTDL dotnet parser provides and object model to inspect DTDL elements: Telemetry, Properties, Commands, Components and Relationships.

All of these are represented as DTEntityInfo elements that must be used with the appropriate DT* types using casting.

To make it easier the navigation through those types, and by using some C# goodness, I've created this DTDL parser C# extensions:

namespace dtdl_dotnet
{
using Microsoft.Azure.DigitalTwins.Parser;
using Microsoft.Azure.DigitalTwins.Parser.Models;
public static class DtmiExtensions
{
public static string ToPath(this Dtmi dtmi) => $"{dtmi.ToString().ToLowerInvariant().Replace(":", "/").Replace(";", "-")}.json";
}
public static class ModelParserExtensions
{
public class InterfaceInfo
{
public IReadOnlyDictionary<Dtmi, DTEntityInfo> ObjectModel;
DTEntityInfo root;
public InterfaceInfo(IReadOnlyDictionary<Dtmi, DTEntityInfo> m)
{
ObjectModel = m;
root = m.Values.Where(v => v.EntityKind == DTEntityKind.Interface).First(e => e.ChildOf == null);
}
public string Id => root.Id.ToString();
public IEnumerable<DTTelemetryInfo> Telemetries =>
((DTInterfaceInfo)root).Contents
.Where(c => c.Value.EntityKind == DTEntityKind.Telemetry)
.Select(t => (DTTelemetryInfo)t.Value);
public IEnumerable<DTPropertyInfo> Properties =>
((DTInterfaceInfo)root).Contents
.Where(c => c.Value.EntityKind == DTEntityKind.Property)
.Select(p => (DTPropertyInfo)p.Value);
public IEnumerable<DTCommandInfo> Commands =>
((DTInterfaceInfo)root).Contents
.Where(c => c.Value.EntityKind == DTEntityKind.Command)
.Select(c => (DTCommandInfo)c.Value);
public IEnumerable<DTComponentInfo> Components =>
((DTInterfaceInfo)root).Contents
.Where(c => c.Value.EntityKind == DTEntityKind.Component)
.Select(c => (DTComponentInfo)c.Value);
public IEnumerable<DTRelationshipInfo> Relationships =>
((DTInterfaceInfo)root).Contents
.Where(c => c.Value.EntityKind == DTEntityKind.Relationship)
.Select(r => (DTRelationshipInfo)r.Value);
}
public static async Task<InterfaceInfo> ParseAsync(this ModelParser parser, string jsonContent)
=> new InterfaceInfo(await parser.ParseAsync(new string[] { jsonContent }));
}
}

That can be used as

var model = await new ModelParser().ParseAsync(ReadFile("dtmi/samples/aninterface-1.json"));

Console.WriteLine(model.Id);

foreach (var t in model.Telemetries)
{
    Console.WriteLine($" [T] {t.Name} {t.Schema.Id}");
}

foreach (var p in model.Properties)
{
    Console.WriteLine($" [P] {p.Name} {p.Schema.Id}");
}

foreach (var c in model.Commands)
{
    Console.WriteLine($" [C] {c.Name} {c.Request.Id} {c.Response.Id}");
}
Enter fullscreen mode Exit fullscreen mode

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (2)

Collapse
 
andypiper profile image
Andy Piper

Interesting. What’s the MQTT element here?

Collapse
 
andypiper profile image
Andy Piper

I'm going to remove the tag, as there is no clear relationship between the post and the MQTT topic.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay