Skip to content

Commit

Permalink
UI: Removing duplicate channels from SubscribeChannels and fix unsubs…
Browse files Browse the repository at this point in the history
…cribing (OpenEMS#2349)

- remove duplicated channels in subscribeChannelsRequest
- liveDataService from Injectable to Directive: lifecycles dont work for Injectables
- added unsubscribeFromChannels, to be able to unsubscribe individual channels without passing the id used for the subscription
- mark unsubscribeChannels as deprecated

Co-authored-by: Lukas Rieger <lukas.rieger@fenecon.de>
  • Loading branch information
mahdiataie and lukasrgr authored Sep 7, 2023
1 parent 96d4a6d commit 28463c4
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 18 deletions.
1 change: 0 additions & 1 deletion ui/src/app/edge/history/history.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export class HistoryComponent implements OnInit {

// is a Timedata service available, i.e. can historic data be queried.
public isTimedataAvailable: boolean = true;

protected errorResponse: JsonrpcResponseError | null = null;

// sets the height for a chart. This is recalculated on every window resize.
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/edge/history/historydataservice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ export class HistoryDataService extends DataService {
}, 100);
}
}

public override unsubscribeFromChannels(channels: ChannelAddress[]) {
return;
}
}
17 changes: 13 additions & 4 deletions ui/src/app/edge/live/livedataservice.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Inject, Injectable, OnDestroy } from "@angular/core";
import { Directive, Inject, OnDestroy } from "@angular/core";
import { takeUntil } from "rxjs/operators";
import { v4 as uuidv4 } from 'uuid';

import { DataService } from "../../shared/genericComponents/shared/dataservice";
import { SubscribeEdgesRequest } from "../../shared/jsonrpc/request/subscribeEdgesRequest";
import { ChannelAddress, Edge, Service, Websocket } from "../../shared/shared";

@Injectable()
@Directive()
export class LiveDataService extends DataService implements OnDestroy {

private subscribeId: string | null = null;
private subscribedChannelAddresses: ChannelAddress[] = [];

constructor(
@Inject(Websocket) protected websocket: Websocket,
Expand All @@ -19,6 +19,11 @@ export class LiveDataService extends DataService implements OnDestroy {
}

public getValues(channelAddresses: ChannelAddress[], edge: Edge, componentId: string) {

for (let channelAddress of channelAddresses) {
this.subscribedChannelAddresses.push(channelAddress);
}

this.subscribeId = uuidv4();
this.edge = edge;
if (channelAddresses.length != 0) {
Expand All @@ -38,8 +43,12 @@ export class LiveDataService extends DataService implements OnDestroy {
}

ngOnDestroy() {
this.websocket.sendRequest(new SubscribeEdgesRequest({ edges: [] }));
this.edge.unsubscribeFromChannels(this.websocket, this.subscribedChannelAddresses);
this.stopOnDestroy.next();
this.stopOnDestroy.complete();
}

public unsubscribeFromChannels(channels: ChannelAddress[]) {
this.edge.unsubscribeFromChannels(this.websocket, channels);
}
}
28 changes: 28 additions & 0 deletions ui/src/app/shared/edge/edge.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { compareVersions } from 'compare-versions';
import { BehaviorSubject, Subject } from 'rxjs';

import { JsonrpcRequest, JsonrpcResponseSuccess } from '../jsonrpc/base';
import { CurrentDataNotification } from '../jsonrpc/notification/currentDataNotification';
import { EdgeConfigNotification } from '../jsonrpc/notification/edgeConfigNotification';
Expand All @@ -12,6 +13,7 @@ import { SubscribeChannelsRequest } from '../jsonrpc/request/subscribeChannelsRe
import { SubscribeSystemLogRequest } from '../jsonrpc/request/subscribeSystemLogRequest';
import { UpdateComponentConfigRequest } from '../jsonrpc/request/updateComponentConfigRequest';
import { GetEdgeConfigResponse } from '../jsonrpc/response/getEdgeConfigResponse';
import { ArrayUtils } from '../service/arrayutils';
import { Websocket } from '../service/websocket';
import { ChannelAddress } from '../type/channeladdress';
import { Role } from '../type/role';
Expand Down Expand Up @@ -120,12 +122,38 @@ export class Edge {
*
* @param websocket the Websocket
* @param id the unique ID for this subscription
* @deprecated Use `unsubscribeFromChannels` instead.
*
* @todo should be removed
*/
public unsubscribeChannels(websocket: Websocket, id: string): void {
delete this.subscribedChannels[id];
this.sendSubscribeChannels(websocket);
}

/**
* Unsubscribes from passed channels
*
* @param websocket the Websocket
* @param channels the channels
*
* @todo should be renamed to `unsubscribeChannels` after unsubscribeChannels is removed
*/
public unsubscribeFromChannels(websocket: Websocket, channels: ChannelAddress[]) {
this.subscribedChannels = Object.entries(this.subscribedChannels).reduce((arr, [id, subscribedChannels]) => {

if (ArrayUtils.equalsCheck(channels.map(channel => channel.toString()), subscribedChannels.map(channel => channel.toString()))) {
return arr;
}

arr[id] = subscribedChannels;

return arr;
}, {});

this.sendSubscribeChannels(websocket);
}

/**
* Subscribe to System-Log
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,12 @@ export abstract class AbstractFlatWidgetLine implements OnChanges, OnDestroy {
/** Channel defines the channel, you need for this line */
@Input()
set channelAddress(channelAddress: string) {
this._channelAddress = ChannelAddress.fromString(channelAddress);
this.subscribe(ChannelAddress.fromString(channelAddress));
}

private _channelAddress: ChannelAddress | null = null;

/**
* displayValue is the displayed @Input value in html
*/
Expand Down Expand Up @@ -71,8 +74,8 @@ export abstract class AbstractFlatWidgetLine implements OnChanges, OnDestroy {

public ngOnDestroy() {
// Unsubscribe from OpenEMS
if (this.edge != null) {
this.edge.unsubscribeChannels(this.websocket, this.selector);
if (this.edge != null && this._channelAddress) {
this.edge.unsubscribeFromChannels(this.websocket, [this._channelAddress]);
}

// Unsubscribe from CurrentData subject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export abstract class AbstractFlatWidget implements OnInit, OnDestroy {
for (let channelId of channelIds) {
channelAddresses.add(new ChannelAddress(this.componentId, channelId));
}

this.dataService.getValues(Array.from(channelAddresses), this.edge, this.componentId);
this.dataService.currentValue.pipe(takeUntil(this.stopOnDestroy)).subscribe(value => {
this.onCurrentData(value);
Expand All @@ -65,8 +64,7 @@ export abstract class AbstractFlatWidget implements OnInit, OnDestroy {
};

public ngOnDestroy() {
// Unsubscribe from OpenEMS
this.edge.unsubscribeChannels(this.websocket, this.selector);
this.dataService.unsubscribeFromChannels(this.getChannelAddresses());

// Unsubscribe from CurrentData subject
this.stopOnDestroy.next();
Expand All @@ -78,8 +76,7 @@ export abstract class AbstractFlatWidget implements OnInit, OnDestroy {
*
* @param currentData new data for the subscribed Channel-Addresses
*/
protected onCurrentData(currentData: CurrentData) {
}
protected onCurrentData(currentData: CurrentData) { }

/**
* Gets the ChannelAddresses that should be subscribed.
Expand Down
9 changes: 8 additions & 1 deletion ui/src/app/shared/genericComponents/shared/dataservice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,12 @@ export abstract class DataService {
* @param edge the edge
* @param componentId the componentId
*/
public abstract getValues(channelAddress: ChannelAddress[], edge: Edge, componentId?: string)
public abstract getValues(channelAddress: ChannelAddress[], edge: Edge, componentId?: string);

/**
* Unsubscribes from passed channels
*
* @param channels the channels
*/
public abstract unsubscribeFromChannels(channels: ChannelAddress[]);
}
2 changes: 1 addition & 1 deletion ui/src/app/shared/header/header.component.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<ion-header>
<ion-toolbar color="primary" mode="md">
<ion-buttons *ngIf="backUrl" slot="start">
<ion-button [routerLink]="backUrl">
<ion-button [routerLink]="backUrl" replaceUrl="true">
<ion-icon name="arrow-back-outline"></ion-icon>
</ion-button>
</ion-buttons>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/shared/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ export class HeaderComponent implements OnInit, OnDestroy, AfterViewChecked {

public segmentChanged(event) {
if (event.detail.value == "IndexLive") {
this.router.navigateByUrl("/device/" + this.service.currentEdge.value.id + "/live", { replaceUrl: true });
this.router.navigate(["/device/" + this.service.currentEdge.value.id + "/live"], { replaceUrl: true });
this.cdRef.detectChanges();
}
if (event.detail.value == "IndexHistory") {
this.router.navigate(['../history'], { relativeTo: this.route });
this.router.navigate(["/device/" + this.service.currentEdge.value.id + "/history"], { replaceUrl: true });
this.cdRef.detectChanges();
}
}
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/shared/jsonrpc/jsonrpcutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { ChannelAddress } from "../type/channeladdress";
export class JsonRpcUtils {

/**
* Converts an array of ChannelAddresses to a string array.
* Converts an array of ChannelAddresses to a string array with unique values.
*/
public static channelsToStringArray(channels: ChannelAddress[]): string[] {
let result = [];
for (let channel of channels) {
result.push(channel.toString());
}
return result;
return Array.from(new Set(result));
}

}
6 changes: 6 additions & 0 deletions ui/src/app/shared/service/arrayutils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export namespace ArrayUtils {
export function equalsCheck(a: any[], b: any[]) {
return a.length === b.length &&
a.every((v, i) => v === b[i]);
}
}

0 comments on commit 28463c4

Please sign in to comment.