Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add describe function #10

Open
ca-d opened this issue May 23, 2023 · 5 comments
Open

Add describe function #10

ca-d opened this issue May 23, 2023 · 5 comments
Assignees
Labels
help wanted Extra attention is needed

Comments

@ca-d
Copy link

ca-d commented May 23, 2023

The Problem

Abstract: It's hard to know whether two different pieces of SCL mean the same configuration, but for some purposes it's important to know.

IEC 61850 purposely offers many structurally different representations of the same configuration data, which means there are syntactically different SCL subtrees with the same semantics. To give just one example, the structure of data communicated by IEDs may be defined either by reference to a common DataTypeTemplates section, or repeated inline within each IED section to exclude the possibility of ambiguity at the cost of increased file size.

For this reason, XML based approaches for diffing and patching documents and subtrees will not do useful work on SCL, even when canonicalised using a standard XML canonicalisation tool. What is needed is a canonical form specifically of SCL data.

Solution idea collection

The solution could take a form similar to

function describe(sclElement: Element, options?: DescribeOptions): Description

where DescribeOptions might allow a user to configure things like whether to consider the desc semantically important or which extension namespaces to take into consideration and where Description is some representation of the semantic content of sclElement:

Don't use XML

We could construct a simple JavaScript object which represents the meaning of a particular element and return that.

This would have the advantage of allowing the describe function to call itself recursively wherever child elements or referenced elements (like external data types) are needed to make sense of the given sclElement.

Canonicalise more

We could return a canonicalised XML string and just canonicalise much harder, removing all descs and irrelevant extension namespaces, inlining all data types into the IEDs that use them, and so forth.

This approach requires us to always fully canonicalise both SCL documents and serialise them out to strings before comparing the full documents, individual subtrees cannot be compared. Also, while allowing for a "line-based" comparison between documents, these lines have nothing at all to do with the original document lines, and anything line-based clashes with OpenSCD's DOM tree manipulation based editing approach. I therefore don't see any significant upsides and am only listing this option because it has been suggested by several parties.

@ca-d ca-d added the help wanted Extra attention is needed label May 23, 2023
@ca-d
Copy link
Author

ca-d commented May 23, 2023

Please add more solution ideas to above collection if you think of any, thanks!

@danyill
Copy link
Collaborator

danyill commented Jun 2, 2023

Thank you for this, I think it is a robust line of argument.

I agree that it is better to describe in JSON than in XML. As an older format it confuses presentation and semantic concerns and I think we want to avoid that in our data structures. I think JSON is "more native" and will allow better precision and more easy manipulation.

There are various tools to convert XSD files to JSON schema and I wonder whether this is worth exploring, so that at least with a tagName or identity we can instantiate default parameters and then manipulate them?

I like this describe function and I think after we get beyond the "simple comparison" and start to subsume child elements we will have many interesting debates about what a description is, and what different kinds of descriptions we can have with reference to use cases.

For instance;

  • We might choose to describe the primary system with or without the secondary system included (LN references)
  • We might choose to describe IEDs with out without communications linkages
  • We might choose to describe IEDs with or without "inlining" the data types
  • We might choose to describe IEDs only with respect to the interfaces they present (not their full data model)
  • and so on...

However if the describe function is built robustly then we will be able to just pass through parameters recursively for the different use cases (hopefully) and be able to use the same base code.

This describe function together which hashing (potentially as a background service and mutation observers) may allow considerable data enrichment and visual amenity, for instance:

  • Showing a change in a bay in the SLD editor when I add an item to a GOOSE dataset without a complex calculation
  • Showing multiple IEDs have the same datasets (often useful to be able to see that two things are "the same" or how many other things are "the same" in a UI)
  • Showing visually on an SLD all the changes between two SCD files (new bays, new IEDs) etc.

@JakobVogelsang
Copy link
Collaborator

I would propose to build a prototype. It seems to me that we will only be able to get the full picture of the complexity here by just doing it. I would propose to start with some used cases from simple to hard:

  • DataTypeTemplates
  • data model structure
  • IED parameters including communication

We can have a kick-off together and there discuss the initial let's go with API for those used cases and see wether we can find some packages to work on.

@ca-d and @danyill what do you think?

@danyill
Copy link
Collaborator

danyill commented Jun 8, 2023

FTR this is where we were at when I stopped: https://github.com/danyill/oscd-compare/blob/pair-faffing/foundation/compare.ts

This is better than the main branch also.

@ca-d
Copy link
Author

ca-d commented Jun 16, 2023

This is what I remember of yesterday's conversation between @danyill, @JakobVogelsang, and myself:

interface DescribeOptions {
  descs: boolean;
  eNSs: string[];
}

type ExtensionNSAttributes = Record<string, Record<string, string | null>>;

interface ExtensibleElementDescription {
  eNSAttributes: ExtensionNSAttributes;
}

interface BaseTypeDescription extends ExtensibleElementDescription {
  privates: string[]; // canonicalized XML of <Private> elements
  texts: string[]; // some representation of <Text> elements
}

interface EnumValDescription extends ExtensibleElementDescription {
  ord?: number;
  desc?: string;
  content?: string;
}

interface EnumTypeDescription extends BaseTypeDescription {
  desc?: string;
  vals: EnumValDescription[];
}

type Description = EnumValDescription | EnumTypeDescription | BDADescription | DATypeDescription | DADescription | DOTypeDescription | DODescription | LNodeTypeDescription | ...

function describe(sclElement: Element, options: DescribeOptions = {descs: true, eNSs: ["http://www.iec.ch/61850/2003/SCLcoordinates", "http://www.w3.org/2001/XMLSchema-instance"]}): Description

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants