Skip to content

Commit

Permalink
Scope query for finding supervision instances more tightly, closes op…
Browse files Browse the repository at this point in the history
  • Loading branch information
danyill committed Feb 8, 2023
1 parent e22e42d commit 4c416fb
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 34 deletions.
76 changes: 48 additions & 28 deletions src/editors/subscription/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,25 @@ export function instantiateSubscriptionSupervision(
]);
}

/**
* Return Val elements within an IED for the control block type
* @param ied - IED SCL element
* @param cbTagName - Either GSEControl or (defaults to) SampledValueControl
* @returns an Element array of Val SCL elements
*/
export function getSupervisionCbRefs(
ied: Element,
cbTagName: string
): Element[] {
const supervisionType = cbTagName === 'GSEControl' ? 'LGOS' : 'LSVS';
const supervisionName = supervisionType === 'LGOS' ? 'GoCBRef' : 'SvCBRef';
return Array.from(
ied.querySelectorAll(
`LN[lnClass="${supervisionType}"]>DOI[name="${supervisionName}"]>DAI[name="setSrcRef"]>Val,LN0[lnClass="${supervisionType}"]>DOI[name="${supervisionName}"]>DAI[name="setSrcRef"]>Val`
)
);
}

/**
* Return an array with a single Delete action to delete the supervision element
* for the given GOOSE/SMV message and subscriber IED.
Expand All @@ -310,12 +329,9 @@ export function removeSubscriptionSupervision(
subscriberIED: Element | undefined
): Delete[] {
if (!controlBlock || !subscriberIED) return [];
const supervisionType =
controlBlock?.tagName === 'GSEControl' ? 'LGOS' : 'LSVS';
const valElement = Array.from(
subscriberIED.querySelectorAll(
`LN[lnClass="${supervisionType}"]>DOI>DAI>Val,LN0[lnClass="${supervisionType}"]>DOI>DAI>Val`
)
const valElement = getSupervisionCbRefs(
subscriberIED,
controlBlock.tagName
).find(val => val.textContent == controlBlockReference(controlBlock));
if (!valElement) return [];
const lnElement = valElement.closest('LN0, LN');
Expand Down Expand Up @@ -361,16 +377,14 @@ function isSupervisionAllowed(
if (subscriberIED.querySelector(`LN[lnClass="${supervisionType}"]`) === null)
return false;
if (
Array.from(
subscriberIED.querySelectorAll(
`LN[lnClass="${supervisionType}"]>DOI>DAI>Val`
)
).find(val => val.textContent == controlBlockReference(controlBlock))
getSupervisionCbRefs(subscriberIED, controlBlock.tagName).find(
val => val.textContent == controlBlockReference(controlBlock)
)
)
return false;
if (
maxSupervisions(subscriberIED, controlBlock) <=
instantiatedSupervisionsCount(subscriberIED, controlBlock, supervisionType)
instantiatedSupervisionsCount(subscriberIED, controlBlock)
)
return false;

Expand All @@ -390,11 +404,17 @@ export function findOrCreateAvailableLNInst(
): Element | null {
let availableLN = Array.from(
subscriberIED.querySelectorAll(`LN[lnClass="${supervisionType}"]`)
).find(
ln =>
ln.querySelector('DOI>DAI>Val') === null ||
ln.querySelector('DOI>DAI>Val')?.textContent === ''
);
).find(ln => {
const supervisionName = supervisionType === 'LGOS' ? 'GoCBRef' : 'SvCBRef';
return (
ln.querySelector(
`DOI[name="${supervisionName}"]>DAI[name="setSrcRef"]>Val`
) === null ||
ln.querySelector(
`DOI[name="${supervisionName}"]>DAI[name="setSrcRef"]>Val`
)?.textContent === ''
);
});
if (!availableLN) {
availableLN = subscriberIED.ownerDocument.createElementNS(
SCL_NAMESPACE,
Expand All @@ -407,13 +427,15 @@ export function findOrCreateAvailableLNInst(
openScdTag.setAttribute('type', 'OpenSCD.create');
availableLN.appendChild(openScdTag);
availableLN.setAttribute('lnClass', supervisionType);
const instantiatedSibling = subscriberIED
.querySelector(`LN[lnClass="${supervisionType}"]>DOI>DAI>Val`)
?.closest('LN');
if (!instantiatedSibling) return null;
const instantiatedSiblings = getSupervisionCbRefs(
subscriberIED,
controlBlock.tagName
).map(val => val.closest('LN'));

if (!instantiatedSiblings || instantiatedSiblings.length === 0) return null;
availableLN.setAttribute(
'lnType',
instantiatedSibling.getAttribute('lnType') ?? ''
instantiatedSiblings[0]!.getAttribute('lnType') ?? ''
);
}

Expand Down Expand Up @@ -508,13 +530,11 @@ export function getExistingSupervision(extRef: Element | null): Element | null {
*/
export function instantiatedSupervisionsCount(
subscriberIED: Element,
controlBlock: Element,
supervisionType: string
controlBlock: Element
): number {
const instantiatedValues = Array.from(
subscriberIED.querySelectorAll(
`LN[lnClass="${supervisionType}"]>DOI>DAI>Val`
)
const instantiatedValues = getSupervisionCbRefs(
subscriberIED,
controlBlock.tagName
).filter(val => val.textContent !== '');
return instantiatedValues.length;
}
Expand Down
8 changes: 2 additions & 6 deletions test/unit/editors/subscription/supervision.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ describe('supervision', () => {

describe('when subscribing to a SampledValueControl', () => {
beforeEach(async () => {
doc = await fetch(
'/test/testfiles/editors/LaterBindingSMV-LSVS.scd'
)
doc = await fetch('/test/testfiles/editors/LaterBindingSMV-LSVS.scd')
.then(response => response.text())
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
});
Expand Down Expand Up @@ -125,9 +123,7 @@ describe('supervision', () => {

describe('when subscribing to a GSEControl', () => {
beforeEach(async () => {
doc = await fetch(
'/test/testfiles/editors/LaterBindingGOOSE-LGOS.scd'
)
doc = await fetch('/test/testfiles/editors/LaterBindingGOOSE-LGOS.scd')
.then(response => response.text())
.then(str => new DOMParser().parseFromString(str, 'application/xml'));
});
Expand Down

0 comments on commit 4c416fb

Please sign in to comment.