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

feat(plugins/Subscription): Create 'Subscription' plugin for GOOSE subscriptions #549

Merged
merged 33 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
562f7ba
Added Subscription ABB plugin
Flurb Feb 15, 2022
2796596
Fix test
Flurb Feb 15, 2022
a611c2f
Added Published GOOSE messages
Flurb Feb 15, 2022
93867d6
First version
Flurb Feb 17, 2022
e313166
Added more fancy UI
Flurb Feb 17, 2022
76a71bf
Refactor
Flurb Feb 17, 2022
cbe324c
Added IED icon
Flurb Feb 20, 2022
c483d2f
Added 3rd group for partially subscribed IEDs
Flurb Feb 21, 2022
eee4738
Small refactoring
Flurb Feb 21, 2022
9492214
Small refactoring
Flurb Feb 21, 2022
2b1af8f
Refactoring
Flurb Feb 21, 2022
44a7274
Added goose message unit test
Flurb Feb 21, 2022
f114ee9
Added unit tests
Flurb Feb 21, 2022
ace3abb
Refactoring
Flurb Feb 22, 2022
d8012fe
Fixing unit test
Flurb Feb 22, 2022
ee8f02e
Merge branch 'main' into subscriber-plugin
Flurb Feb 22, 2022
6db5c50
Merge branch 'main' into subscriber-plugin
Flurb Feb 22, 2022
e1d63f7
Bugfix
Flurb Feb 23, 2022
11e0856
Another bug fix
Flurb Feb 23, 2022
34d8f64
Made both lists scrollable
Flurb Feb 23, 2022
969a6d2
Review comments
Flurb Feb 24, 2022
739a6fc
Review comments
Flurb Feb 24, 2022
3138936
Review comments
Flurb Feb 24, 2022
7910be6
Review comments
Flurb Feb 24, 2022
3270b66
Fixing tests
Flurb Feb 24, 2022
240a076
Adjusted styling
Flurb Feb 24, 2022
74a405a
Small refactoring
Flurb Feb 25, 2022
e65ee85
Added German translations
Flurb Feb 28, 2022
9074b43
Review comments
Flurb Feb 28, 2022
d24117c
Review comments
Flurb Mar 4, 2022
adf73bf
Renaming
Flurb Mar 4, 2022
204e6bb
feat(plugins/Subscription): Manage GOOSE service connections (#569)
Flurb Mar 17, 2022
66b3674
Merge with main
Flurb Mar 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions public/js/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ export const officialPlugins = [
default: false,
kind: 'editor',
},
{
name: 'Subscription',
src: '/src/editors/Subscription.js',
icon: 'link',
default: true,
kind: 'editor',
},
{
name: 'Communication',
src: '/src/editors/Communication.js',
Expand Down
49 changes: 49 additions & 0 deletions src/editors/Subscription.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { LitElement, html, TemplateResult, property, css } from 'lit-element';

import '@material/mwc-fab';

import './subscription/subscriber-ied-list.js';
import './subscription/publisher-goose-list.js';

/** An editor [[`plugin`]] for subscribing IEDs to GOOSE messages using the ABB subscription method. */
export default class SubscriptionABBPlugin extends LitElement {
Flurb marked this conversation as resolved.
Show resolved Hide resolved
/** The document being edited as provided to plugins by [[`OpenSCD`]]. */
@property()
doc!: XMLDocument;

render(): TemplateResult {
return html`
<div id="containerTemplates">
<section>
<publisher-goose-list .doc=${this.doc}></publisher-goose-list>
</section>
<section>
<subscriber-ied-list .doc=${this.doc}></subscriber-ied-list>
</section>
</div>`;
}

static styles = css`
:host {
width: 100vw;
}

section {
width: 49vw;
}

#containerTemplates {
display: grid;
grid-gap: 12px;
padding: 8px 12px 16px;
box-sizing: border-box;
grid-template-columns: repeat(auto-fit, minmax(316px, auto));
}

@media (max-width: 387px) {
#containerTemplates {
grid-template-columns: repeat(auto-fit, minmax(196px, auto));
}
}
`;
}
40 changes: 40 additions & 0 deletions src/editors/subscription/goose-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
css,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';
import { newGOOSEDataSetEvent } from '../../foundation.js';
import { gooseIcon } from '../../icons.js';

@customElement('goose-message')
export class GOOSEMessage extends LitElement {
/** Holding the GSEControl element */
@property({ attribute: false })
element!: Element;

private onGooseSelect = () => {
const ln = this.element.parentElement;
const dataset = ln?.querySelector(`DataSet[name=${this.element.getAttribute('datSet')}]`);
document.querySelector('open-scd')!.dispatchEvent(
newGOOSEDataSetEvent(
this.element.closest('IED')?.getAttribute('name') ?? '',
this.element.getAttribute('name') ?? '',
dataset!
)
);
};

render(): TemplateResult {
return html`<mwc-list-item
@click=${this.onGooseSelect}
graphic="large">
<span>${this.element.getAttribute('name')}</span>
<mwc-icon slot="graphic">${gooseIcon}</mwc-icon>
</mwc-list-item>`;
}

static styles = css``;
}
73 changes: 73 additions & 0 deletions src/editors/subscription/publisher-goose-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
css,
customElement,
html,
LitElement,
property,
TemplateResult,
} from 'lit-element';

import './goose-message.js';

import { translate } from 'lit-translate';
import { compareNames, getNameAttribute } from '../../foundation.js';
import { styles } from '../templates/foundation.js';

/** An sub element for showing all published GOOSE messages per IED. */
@customElement('publisher-goose-list')
export class PublisherGOOSEList extends LitElement {
@property()
doc!: XMLDocument;

private get ieds() : Element[] {
return (this.doc)
? Array.from(this.doc.querySelectorAll(':root > IED')).sort((a,b) => compareNames(a,b))
: [];
}

/**
* Get all the published GOOSE messages.
* @param ied - The IED to search through.
* @returns All the published GOOSE messages of this specific IED.
*/
private getGSEControls(ied: Element) : Element[] {
return Array.from(ied.querySelectorAll(':scope > AccessPoint > Server > LDevice > LN0[lnClass="LLN0"] > GSEControl'));
}

render(): TemplateResult {
return html`
<section>
<h1>${translate('subscription.publisherGoose.title')}</h1>
<mwc-list>
${this.ieds.map(ied =>
ied.querySelector('GSEControl') ?
html`
<mwc-list-item noninteractive graphic="icon">
<span class="iedListTitle">${getNameAttribute(ied)}</span>
<mwc-icon slot="graphic">developer_board</mwc-icon>
</mwc-list-item>
<li divider role="separator"></li>
${this.getGSEControls(ied).map(control =>
html`<goose-message
.element=${control}
></goose-message>`)}
` : ``
)
}
</mwc-list>
</section>`;
}

static styles = css`
${styles}

mwc-list {
height: 100vh;
overflow-y: scroll;
}

.iedListTitle {
font-weight: bold;
}
`;
}
Loading