openscd / oscd-scl Goto Github PK
View Code? Open in Web Editor NEWLicense: Apache License 2.0
License: Apache License 2.0
As a plugin author, I need to identify the reference
key using the Insert
type edit-event
.
Requirements
getReference(parent: Element, tagName: string): Element | null
Additional Information
The function getReference
is needed every time an insert type edit
event is sent to open-scd-core
. The Insert
object has a required key reference
that tells where within the parent
the new node
must be inserted. This reference
can be retrieved though getReference
.
We can get this function from open-scd
s foundation.ts
. Proper testing could be tricky as we do not have a mechanism to randomly create an element based on the schema. We have to start with testing some edge case components.
As a plugin author is need to determine all child element tags and parent element tags. The child element tags must be in the same order is defined by the sequence in the schema.
Requirements
parentTags(tagName: string): string[]
childTags(tagName: string): string[]
Additional Information
We need both the functions parantTags
and childTags
in a lot of foundation functions such as getReference
that allows to get the reference
while inserting a new element to the SCL. This is important because most of the elements in the SCL are defined in sequences and therefore the location of the element matters
The newest commit containing the find
function cannot be build and published. As far as I can see the
I am sorry for the sloppy work of mine. I shall correct as soon as possible.
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.
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
:
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
.
We could return a canonicalised XML string
and just canonicalise much harder, removing all desc
s and irrelevant extension namespaces, inlining all data types into the IED
s 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.
As a plugin author, I want to have an identity string for a given SCL Element.
Requirements:
identity(element: Element): string | number
Additional Information:
Such an identity string is required every time we cannot pass the SCL Element itself, but only a string. Then such an identity string with proper query function allow to still attach an Element to a UI element and use it on user interaction.
We also use it heavily to indicate an Element's position in the SCL file. E.g. a GOOSE control blocks location in an IED.
Since identity
strings are being used in several places in the user interface, the path-like /
may be an easier separator for users to read than the CSS-selector-like >
.
Note
At first glance it looks to me like the character /
is forbidden by the standard in all identity relevant attribute fields, just like >
is, so there should be no corner cases where we run into trouble. Nonetheless, it would be worth checking all relevant types in the schema before making the change.
Describe the bug
Uniqueness of the SCL ExtRef element is difficult and we have a complex identity
function to do this job. The identity
function appears to correctly identify ExtRefs with the same intAddr
but the selector
function does not.
For a specific case which happens to occur in one of our testfiles where we have:
<ExtRef xmlns="http://www.iec.ch/61850/2003/SCL" intAddr="someRestrictedExtRef" desc="Restricted To Pos" pLN="CSWI" pDO="Pos" pDA="q" pServT="GOOSE"/>
<ExtRef xmlns="http://www.iec.ch/61850/2003/SCL" intAddr="someRestrictedExtRef" desc="Restricted To Pos" pLN="CSWI" pDO="Pos" pDA="stVal" pServT="GOOSE"/>
We produce the identities for these of:
'GOOSE_Subscriber>>Earth_Switch> CSWI 1>someRestrictedExtRef[0]'
'GOOSE_Subscriber>>Earth_Switch> CSWI 1>someRestrictedExtRef[1]
But the same (complicated!) selector function:
'IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch> CSWI 1"]>LN0>Inputs>ExtRef[intAddr="someRestrictedExtRef"],IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch"]>LN:not([prefix])[lnClass="CSWI"][inst="1"]>Inputs>ExtRef[intAddr="someRestrictedExtRef"],IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch"]>LN[prefix=""][lnClass="CSWI"][inst="1"]>Inputs>ExtRef[intAddr="someRestrictedExtRef"]'
'IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch> CSWI 1"]>LN0>Inputs>ExtRef[intAddr="someRestrictedExtRef"],IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch"]>LN:not([prefix])[lnClass="CSWI"][inst="1"]>Inputs>ExtRef[intAddr="someRestrictedExtRef"],IED[name="GOOSE_Subscriber"] LDevice[inst="Earth_Switch"]>LN[prefix=""][lnClass="CSWI"][inst="1"]>Inputs>ExtRef[intAddr="someRestrictedExtRef"]'
To Reproduce
Steps to reproduce the behavior:
test/testfiles/editors/LaterBindingGOOSE2007B4.scd
Expected behavior
Either
(a) it is illegitimate to have two ExtRefs identified by the same intAddr
(b) the selector function must support indexing.
It seems an anti-pattern to have two ExtRefs with the same intAddr
, but it seems possible (and within the same Inputs section) from the standard. I could imagine doing this while specifying the pXX
attributes to allow "parts" of an SPS to be mapped.
Additional context
While moving later-binding subscription to a core plugin (temporarily, here), I noticed this as I was storing the identity in a data-extref
field and then using the selector to find the element rather than using closures as we do in our present plugin. Referencing the incorrect ExtRef was quite apparent to me there as it resulted in incorrect behaviour when unsubscribing.
When I get the identity for a GSE
or SMV
element, there is no clear path in it for a specific ConnectedAP
:
identity(address)
'MUSV smvcb1'
selector('SMV', identity(address))
'SMV[ldInst="MUSV"][cbName="smvcb1"]'
As a result, the identity of these elements as described is not unique, it must be qualified by the ConnectedAP
and possibly the SubNetwork
.
Similarly, the code for selector in open-scd
seems to have the same limitations.
Lines 172 to 184 in 2df4a18
I've not written an identity/selector function before but I think what we need is something like:
export function controlBlockIdentity(e: Element): string {
const [ldInst, cbName] = ['ldInst', 'cbName'].map(name =>
e.getAttribute(name)
);
return `${identity(e.parentElement)}>${ldInst} ${cbName}`;
}
export function controlBlockSelector(
tagName: SCLTag,
identity: string
): string {
const [parentIdentity, cbIdentity] = identity.split('>');
const [ldInst, cbName] = cbIdentity.split(' ');
if (!ldInst || !cbName) return voidSelector;
const parents = relatives[tagName].parents.map(parent =>
selector(parent, parentIdentity)
);
return crossProduct(
parents,
['>'],
[`${tagName}[ldInst="${ldInst}"][cbName="${cbName}"]`]
)
.map(strings => strings.join(''))
.join(',');
}
If that seems about right I am happy to do a PR.
As a plugin author, I want to get an SCL Element based on a given identity string.
Requirements:
query(root:XMLDocument | Element, tagName: string, identity: string): Element | null
Additional Information:
It is included in open-scd
already and can be moved, including tests.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.